@opensaas/keystone-nextjs-auth 21.1.0 → 22.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  });