@opensaas/keystone-nextjs-auth 21.1.0 → 22.1.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.
@@ -3,12 +3,10 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
6
- var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
7
6
  var NextAuth = require('next-auth');
8
7
 
9
8
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
10
9
 
11
- var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
12
10
  var NextAuth__default = /*#__PURE__*/_interopDefault(NextAuth);
13
11
 
14
12
  async function findMatchingIdentity(identityField, identity, queryAPI) {
@@ -70,9 +68,7 @@ function NextAuthPage(props) {
70
68
  resolver,
71
69
  sessionData,
72
70
  sessionSecret
73
- } = props; // TODO: (v1.1). https://github.com/ijsto/keystone-6-oauth/projects/1#card-78602004
74
-
75
- console.log('NextAuthPages... ', pages);
71
+ } = props;
76
72
 
77
73
  if (!query) {
78
74
  console.error('NextAuthPage got no query.');
@@ -123,26 +119,42 @@ function NextAuthPage(props) {
123
119
 
124
120
  if (!result.success) {
125
121
  if (!autoCreate) {
126
- console.log('`autoCreate` if set to `false`, skipping user auto-creation');
122
+ console.log('`autoCreate` is set to `false`, skipping user auto-creation');
127
123
  return false;
128
124
  }
129
125
 
130
- console.log('`autoCreate` if set to `true`, auto-creating a new user');
126
+ console.log('`autoCreate` is set to `true`, auto-creating a new user');
131
127
  const createUser = await list.createOne({
132
128
  data
133
129
  }).then(returned => {
134
- console.log('User Created', _JSON$stringify__default["default"](returned));
135
- return true;
130
+ return {
131
+ success: true,
132
+ user: returned
133
+ };
136
134
  }).catch(error => {
137
135
  console.log(error);
138
136
  throw new Error(error);
139
137
  });
140
138
  console.log('Created User', createUser);
141
- return createUser;
142
- } // await list.updateOne({where: {id: result.item.id}, data});
143
-
139
+ return createUser.success;
140
+ }
144
141
 
145
- return result.success;
142
+ console.log('Data', data);
143
+ const updateUser = await list.updateOne({
144
+ where: {
145
+ id: result.item.id
146
+ },
147
+ data
148
+ }).then(returned => {
149
+ return {
150
+ success: true,
151
+ user: returned
152
+ };
153
+ }).catch(error => {
154
+ console.log(error);
155
+ throw new Error(error);
156
+ });
157
+ return updateUser.success;
146
158
  },
147
159
 
148
160
  async redirect({
@@ -155,13 +167,22 @@ function NextAuthPage(props) {
155
167
  session,
156
168
  token
157
169
  }) {
158
- const returnSession = _objectSpread(_objectSpread({}, session), {}, {
159
- data: token.data,
160
- subject: token.sub,
161
- listKey: token.listKey,
162
- itemId: token.itemId
163
- });
170
+ let returnSession = session;
171
+
172
+ if (!token.itemId) {
173
+ return {
174
+ expires: '0'
175
+ };
176
+ } else {
177
+ returnSession = _objectSpread(_objectSpread({}, session), {}, {
178
+ data: token.data,
179
+ subject: token.sub,
180
+ listKey: token.listKey,
181
+ itemId: token.itemId
182
+ });
183
+ }
164
184
 
185
+ console.log('Session', returnSession);
165
186
  return returnSession;
166
187
  },
167
188
 
@@ -169,26 +190,22 @@ function NextAuthPage(props) {
169
190
  token
170
191
  }) {
171
192
  const identity = token.sub;
193
+ const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
172
194
 
173
- if (!token.itemId) {
174
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
175
-
176
- if (!result.success) {
177
- return token;
178
- }
179
-
195
+ if (!result.success) {
196
+ token.itemId = null;
197
+ } else {
180
198
  token.itemId = result.item.id;
199
+ const data = await query[listKey].findOne({
200
+ where: {
201
+ id: token.itemId
202
+ },
203
+ query: sessionData || 'id'
204
+ });
205
+ token.data = data;
181
206
  }
182
207
 
183
- const data = await query[listKey].findOne({
184
- where: {
185
- id: token.itemId
186
- },
187
- query: sessionData || 'id'
188
- });
189
-
190
208
  const returnToken = _objectSpread(_objectSpread({}, token), {}, {
191
- data,
192
209
  subject: token.sub,
193
210
  listKey
194
211
  });
@@ -3,12 +3,10 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
6
- var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
7
6
  var NextAuth = require('next-auth');
8
7
 
9
8
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
10
9
 
11
- var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
12
10
  var NextAuth__default = /*#__PURE__*/_interopDefault(NextAuth);
13
11
 
14
12
  async function findMatchingIdentity(identityField, identity, queryAPI) {
@@ -70,9 +68,7 @@ function NextAuthPage(props) {
70
68
  resolver,
71
69
  sessionData,
72
70
  sessionSecret
73
- } = props; // TODO: (v1.1). https://github.com/ijsto/keystone-6-oauth/projects/1#card-78602004
74
-
75
- console.log('NextAuthPages... ', pages);
71
+ } = props;
76
72
 
77
73
  if (!query) {
78
74
  console.error('NextAuthPage got no query.');
@@ -123,26 +119,42 @@ function NextAuthPage(props) {
123
119
 
124
120
  if (!result.success) {
125
121
  if (!autoCreate) {
126
- console.log('`autoCreate` if set to `false`, skipping user auto-creation');
122
+ console.log('`autoCreate` is set to `false`, skipping user auto-creation');
127
123
  return false;
128
124
  }
129
125
 
130
- console.log('`autoCreate` if set to `true`, auto-creating a new user');
126
+ console.log('`autoCreate` is set to `true`, auto-creating a new user');
131
127
  const createUser = await list.createOne({
132
128
  data
133
129
  }).then(returned => {
134
- console.log('User Created', _JSON$stringify__default["default"](returned));
135
- return true;
130
+ return {
131
+ success: true,
132
+ user: returned
133
+ };
136
134
  }).catch(error => {
137
135
  console.log(error);
138
136
  throw new Error(error);
139
137
  });
140
138
  console.log('Created User', createUser);
141
- return createUser;
142
- } // await list.updateOne({where: {id: result.item.id}, data});
143
-
139
+ return createUser.success;
140
+ }
144
141
 
145
- return result.success;
142
+ console.log('Data', data);
143
+ const updateUser = await list.updateOne({
144
+ where: {
145
+ id: result.item.id
146
+ },
147
+ data
148
+ }).then(returned => {
149
+ return {
150
+ success: true,
151
+ user: returned
152
+ };
153
+ }).catch(error => {
154
+ console.log(error);
155
+ throw new Error(error);
156
+ });
157
+ return updateUser.success;
146
158
  },
147
159
 
148
160
  async redirect({
@@ -155,13 +167,22 @@ function NextAuthPage(props) {
155
167
  session,
156
168
  token
157
169
  }) {
158
- const returnSession = _objectSpread(_objectSpread({}, session), {}, {
159
- data: token.data,
160
- subject: token.sub,
161
- listKey: token.listKey,
162
- itemId: token.itemId
163
- });
170
+ let returnSession = session;
171
+
172
+ if (!token.itemId) {
173
+ return {
174
+ expires: '0'
175
+ };
176
+ } else {
177
+ returnSession = _objectSpread(_objectSpread({}, session), {}, {
178
+ data: token.data,
179
+ subject: token.sub,
180
+ listKey: token.listKey,
181
+ itemId: token.itemId
182
+ });
183
+ }
164
184
 
185
+ console.log('Session', returnSession);
165
186
  return returnSession;
166
187
  },
167
188
 
@@ -169,26 +190,22 @@ function NextAuthPage(props) {
169
190
  token
170
191
  }) {
171
192
  const identity = token.sub;
193
+ const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
172
194
 
173
- if (!token.itemId) {
174
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
175
-
176
- if (!result.success) {
177
- return token;
178
- }
179
-
195
+ if (!result.success) {
196
+ token.itemId = null;
197
+ } else {
180
198
  token.itemId = result.item.id;
199
+ const data = await query[listKey].findOne({
200
+ where: {
201
+ id: token.itemId
202
+ },
203
+ query: sessionData || 'id'
204
+ });
205
+ token.data = data;
181
206
  }
182
207
 
183
- const data = await query[listKey].findOne({
184
- where: {
185
- id: token.itemId
186
- },
187
- query: sessionData || 'id'
188
- });
189
-
190
208
  const returnToken = _objectSpread(_objectSpread({}, token), {}, {
191
- data,
192
209
  subject: token.sub,
193
210
  listKey
194
211
  });
@@ -1,5 +1,4 @@
1
1
  import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
2
- import _JSON$stringify from '@babel/runtime-corejs3/core-js-stable/json/stringify';
3
2
  import NextAuth from 'next-auth';
4
3
 
5
4
  async function findMatchingIdentity(identityField, identity, queryAPI) {
@@ -61,9 +60,7 @@ function NextAuthPage(props) {
61
60
  resolver,
62
61
  sessionData,
63
62
  sessionSecret
64
- } = props; // TODO: (v1.1). https://github.com/ijsto/keystone-6-oauth/projects/1#card-78602004
65
-
66
- console.log('NextAuthPages... ', pages);
63
+ } = props;
67
64
 
68
65
  if (!query) {
69
66
  console.error('NextAuthPage got no query.');
@@ -114,26 +111,42 @@ function NextAuthPage(props) {
114
111
 
115
112
  if (!result.success) {
116
113
  if (!autoCreate) {
117
- console.log('`autoCreate` if set to `false`, skipping user auto-creation');
114
+ console.log('`autoCreate` is set to `false`, skipping user auto-creation');
118
115
  return false;
119
116
  }
120
117
 
121
- console.log('`autoCreate` if set to `true`, auto-creating a new user');
118
+ console.log('`autoCreate` is set to `true`, auto-creating a new user');
122
119
  const createUser = await list.createOne({
123
120
  data
124
121
  }).then(returned => {
125
- console.log('User Created', _JSON$stringify(returned));
126
- return true;
122
+ return {
123
+ success: true,
124
+ user: returned
125
+ };
127
126
  }).catch(error => {
128
127
  console.log(error);
129
128
  throw new Error(error);
130
129
  });
131
130
  console.log('Created User', createUser);
132
- return createUser;
133
- } // await list.updateOne({where: {id: result.item.id}, data});
134
-
131
+ return createUser.success;
132
+ }
135
133
 
136
- return result.success;
134
+ console.log('Data', data);
135
+ const updateUser = await list.updateOne({
136
+ where: {
137
+ id: result.item.id
138
+ },
139
+ data
140
+ }).then(returned => {
141
+ return {
142
+ success: true,
143
+ user: returned
144
+ };
145
+ }).catch(error => {
146
+ console.log(error);
147
+ throw new Error(error);
148
+ });
149
+ return updateUser.success;
137
150
  },
138
151
 
139
152
  async redirect({
@@ -146,13 +159,22 @@ function NextAuthPage(props) {
146
159
  session,
147
160
  token
148
161
  }) {
149
- const returnSession = _objectSpread(_objectSpread({}, session), {}, {
150
- data: token.data,
151
- subject: token.sub,
152
- listKey: token.listKey,
153
- itemId: token.itemId
154
- });
162
+ let returnSession = session;
163
+
164
+ if (!token.itemId) {
165
+ return {
166
+ expires: '0'
167
+ };
168
+ } else {
169
+ returnSession = _objectSpread(_objectSpread({}, session), {}, {
170
+ data: token.data,
171
+ subject: token.sub,
172
+ listKey: token.listKey,
173
+ itemId: token.itemId
174
+ });
175
+ }
155
176
 
177
+ console.log('Session', returnSession);
156
178
  return returnSession;
157
179
  },
158
180
 
@@ -160,26 +182,22 @@ function NextAuthPage(props) {
160
182
  token
161
183
  }) {
162
184
  const identity = token.sub;
185
+ const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
163
186
 
164
- if (!token.itemId) {
165
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
166
-
167
- if (!result.success) {
168
- return token;
169
- }
170
-
187
+ if (!result.success) {
188
+ token.itemId = null;
189
+ } else {
171
190
  token.itemId = result.item.id;
191
+ const data = await query[listKey].findOne({
192
+ where: {
193
+ id: token.itemId
194
+ },
195
+ query: sessionData || 'id'
196
+ });
197
+ token.data = data;
172
198
  }
173
199
 
174
- const data = await query[listKey].findOne({
175
- where: {
176
- id: token.itemId
177
- },
178
- query: sessionData || 'id'
179
- });
180
-
181
200
  const returnToken = _objectSpread(_objectSpread({}, token), {}, {
182
- data,
183
201
  subject: token.sub,
184
202
  listKey
185
203
  });
@@ -17,10 +17,7 @@ export function getBaseAuthSchema({
17
17
  resolveType: (root, context) => context.session?.listKey,
18
18
  }),
19
19
  resolve(root, args, { session, db }) {
20
- if (
21
- typeof session?.itemId === 'string' &&
22
- typeof session.listKey === 'string'
23
- ) {
20
+ if (typeof session?.itemId === 'string' && typeof session.listKey === 'string') {
24
21
  return db[session.listKey].findOne({
25
22
  where: { id: session.itemId },
26
23
  });
package/src/index.ts CHANGED
@@ -5,8 +5,8 @@ import {
5
5
  KeystoneConfig,
6
6
  KeystoneContext,
7
7
  AdminUIConfig,
8
- SessionStrategy,
9
8
  BaseKeystoneTypeInfo,
9
+ SessionStrategy,
10
10
  } from '@keystone-6/core/types';
11
11
  import { getSession } from 'next-auth/react';
12
12
  import { getToken } from 'next-auth/jwt';
@@ -14,10 +14,11 @@ import { Provider } from 'next-auth/providers';
14
14
 
15
15
  import * as cookie from 'cookie';
16
16
 
17
+ import { Session } from 'next-auth';
17
18
  import { nextConfigTemplate } from './templates/next-config';
18
19
  // import * as Path from 'path';
19
20
 
20
- import { AuthConfig, KeystoneOAuthConfig, NextAuthSession } from './types';
21
+ import { AuthConfig, KeystoneOAuthConfig, AuthSessionStrategy } from './types';
21
22
  import { getSchemaExtension } from './schema';
22
23
  import { authTemplate } from './templates/auth';
23
24
 
@@ -56,31 +57,41 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
56
57
  * - to the init page when initFirstItem is configured, and there are no user in the database
57
58
  * - to the signin page when no valid session is present
58
59
  */
59
- const pageMiddleware: AdminUIConfig<BaseKeystoneTypeInfo>['pageMiddleware'] =
60
- async ({ context, isValidSession }) => {
61
- const { req, session } = context;
62
- const pathname = url.parse(req?.url!).pathname!;
60
+ const pageMiddleware: AdminUIConfig<BaseKeystoneTypeInfo>['pageMiddleware'] = async ({
61
+ context,
62
+ isValidSession,
63
+ }) => {
64
+ const { req, session } = context;
65
+ const pathname = url.parse(req?.url!).pathname!;
63
66
 
64
- if (isValidSession) {
65
- if (pathname === `${customPath}/api/auth/signin`) {
66
- return { kind: 'redirect', to: `${customPath}` };
67
- }
68
- if (customPath !== '' && pathname === '/') {
69
- return { kind: 'redirect', to: `${customPath}` };
70
- }
71
- return;
72
- }
73
- if (pathname.includes('/_next/') || pathname.includes('/api/auth/')) {
74
- return;
75
- }
67
+ if (isValidSession) {
76
68
  if (
77
- !session &&
78
- !pathname.includes(`${customPath}/api/auth/`) &&
79
- !(Object.values(pages).indexOf(pathname) > -1)
69
+ pathname === `${customPath}/api/auth/signin` ||
70
+ (pages?.signIn && pathname.includes(pages?.signIn))
80
71
  ) {
81
- return { kind: 'redirect', to: `${customPath}/api/auth/signin` };
72
+ return { kind: 'redirect', to: `${customPath}` };
82
73
  }
83
- };
74
+ if (customPath !== '' && pathname === '/') {
75
+ return { kind: 'redirect', to: `${customPath}` };
76
+ }
77
+ return;
78
+ }
79
+ if (
80
+ pathname.includes('/_next/') ||
81
+ pathname.includes('/api/auth/') ||
82
+ (pages?.signIn && pathname.includes(pages?.signIn)) ||
83
+ (pages?.error && pathname.includes(pages?.error)) ||
84
+ (pages?.signOut && pathname.includes(pages?.signOut))
85
+ ) {
86
+ return;
87
+ }
88
+ if (!session && !pathname.includes(`${customPath}/api/auth/`)) {
89
+ return {
90
+ kind: 'redirect',
91
+ to: pages?.signIn || `${customPath}/api/auth/signin`,
92
+ };
93
+ }
94
+ };
84
95
 
85
96
  /**
86
97
  * getAdditionalFiles
@@ -181,37 +192,46 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
181
192
  - [ ] We could support additional where input to validate item sessions (e.g an isEnabled boolean)
182
193
  */
183
194
  const withItemData = (
184
- _sessionStrategy: SessionStrategy<Record<string, any>>
185
- ): SessionStrategy<NextAuthSession | undefined> => {
186
- const { get, start, ...sessionStrategy } = _sessionStrategy;
195
+ _sessionStrategy: AuthSessionStrategy<Record<string, any>>
196
+ ): AuthSessionStrategy<{ listKey: string; itemId: string; data: any }> => {
197
+ const { get, ...sessionStrategy } = _sessionStrategy;
187
198
  return {
188
199
  ...sessionStrategy,
189
- start: async ({ res }) => {
190
- console.log('start');
191
-
192
- const session = await start({ res });
193
- return session;
200
+ start: async () => {
201
+ return 'false';
194
202
  },
195
- get: async ({ req }) => {
203
+ get: async ({ req, createContext }) => {
204
+ const sudoContext = createContext({ sudo: true });
196
205
  const pathname = url.parse(req?.url!).pathname!;
206
+ let nextSession: Session;
197
207
  if (pathname.includes('/api/auth')) {
198
208
  return;
199
209
  }
200
- if (req.headers.authorization?.split(' ')[0] === 'Bearer') {
201
- const token = (await getToken({
210
+ if (req.headers?.authorization?.split(' ')[0] === 'Bearer') {
211
+ nextSession = (await getToken({
202
212
  req,
203
213
  secret: sessionSecret,
204
- })) as NextAuthSession;
205
-
206
- if (token?.data?.id) {
207
- return token;
208
- }
214
+ })) as Session;
215
+ } else {
216
+ nextSession = (await getSession({ req })) as Session;
209
217
  }
210
- const nextSession: unknown = await getSession({ req });
211
218
 
212
- if (nextSession) {
213
- return nextSession as NextAuthSession;
219
+ if (
220
+ !nextSession ||
221
+ !nextSession.listKey ||
222
+ nextSession.listKey !== listKey ||
223
+ !nextSession.itemId ||
224
+ !sudoContext.query[listKey] ||
225
+ !nextSession.itemId
226
+ ) {
227
+ return;
214
228
  }
229
+ return {
230
+ ...nextSession,
231
+ data: nextSession.data,
232
+ listKey: nextSession.listKey,
233
+ itemId: nextSession.itemId,
234
+ };
215
235
  },
216
236
  end: async ({ res, req }) => {
217
237
  const TOKEN_NAME =
@@ -252,13 +272,9 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
252
272
  ui = {
253
273
  ...keystoneConfig.ui,
254
274
  publicPages: [...(keystoneConfig.ui.publicPages || []), ...publicPages],
255
- getAdditionalFiles: [
256
- ...(keystoneConfig.ui?.getAdditionalFiles || []),
257
- getAdditionalFiles,
258
- ],
259
- pageMiddleware: async (args) =>
260
- (await pageMiddleware(args)) ??
261
- keystoneConfig?.ui?.pageMiddleware?.(args),
275
+ getAdditionalFiles: [...(keystoneConfig.ui?.getAdditionalFiles || []), getAdditionalFiles],
276
+ pageMiddleware: async args =>
277
+ (await pageMiddleware(args)) ?? keystoneConfig?.ui?.pageMiddleware?.(args),
262
278
  enableSessionItem: true,
263
279
  isAccessAllowed: async (context: KeystoneContext) => {
264
280
  const { req } = context;
@@ -286,9 +302,8 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
286
302
  };
287
303
  }
288
304
 
289
- if (!keystoneConfig.session)
290
- throw new TypeError('Missing .session configuration');
291
- const session = withItemData(keystoneConfig.session);
305
+ if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
306
+ const session = withItemData(keystoneConfig.session) as SessionStrategy<any>;
292
307
 
293
308
  const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
294
309
  return {
@@ -307,7 +322,7 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
307
322
  generateNodeAPI: true,
308
323
  },
309
324
  extendGraphqlSchema: existingExtendGraphQLSchema
310
- ? (schema) => existingExtendGraphQLSchema(extendGraphqlSchema(schema))
325
+ ? schema => existingExtendGraphQLSchema(extendGraphqlSchema(schema))
311
326
  : extendGraphqlSchema,
312
327
  };
313
328
  };
@@ -4,10 +4,7 @@ export async function findMatchingIdentity(
4
4
  identityField: string,
5
5
  identity: string | number,
6
6
  queryAPI: any
7
- ): Promise<
8
- | { success: false; code: AuthTokenRequestErrorCode }
9
- | { success: true; item: any }
10
- > {
7
+ ): Promise<{ success: false; code: AuthTokenRequestErrorCode } | { success: true; item: any }> {
11
8
  const item = await queryAPI.findOne({
12
9
  where: { [identityField]: identity },
13
10
  });