@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.
@@ -1,14 +1,9 @@
1
- import NextAuth, {
2
- CookiesOptions,
3
- EventCallbacks,
4
- PagesOptions,
5
- } from 'next-auth';
1
+ import NextAuth, { CookiesOptions, EventCallbacks, PagesOptions } from 'next-auth';
6
2
  import type { KeystoneListsAPI } from '@keystone-6/core/types';
7
3
  import { Provider } from 'next-auth/providers';
8
4
  import { JWTOptions } from 'next-auth/jwt';
9
5
  import { validateNextAuth } from '../lib/validateNextAuth';
10
6
 
11
- // TODO: See if possible to merge with `type AuthConfig`
12
7
  type CoreNextAuthPageProps = {
13
8
  autoCreate: boolean;
14
9
  cookies?: Partial<CookiesOptions>;
@@ -18,7 +13,9 @@ type CoreNextAuthPageProps = {
18
13
  listKey: string;
19
14
  pages?: Partial<PagesOptions>;
20
15
  providers?: Provider[];
21
- resolver?: Function | undefined;
16
+ resolver?: (args: { user: any; profile: any; account: any }) => {
17
+ [key: string]: boolean | string | number;
18
+ };
22
19
  sessionData: string | undefined;
23
20
  sessionSecret: string;
24
21
  };
@@ -45,8 +42,6 @@ export default function NextAuthPage(props: NextAuthPageProps) {
45
42
  sessionData,
46
43
  sessionSecret,
47
44
  } = props;
48
- // TODO: (v1.1). https://github.com/ijsto/keystone-6-oauth/projects/1#card-78602004
49
- console.log('NextAuthPages... ', pages);
50
45
 
51
46
  if (!query) {
52
47
  console.error('NextAuthPage got no query.');
@@ -79,16 +74,9 @@ export default function NextAuthPage(props: NextAuthPageProps) {
79
74
  } else {
80
75
  identity = 0;
81
76
  }
82
- const userInput = resolver
83
- ? await resolver({ user, account, profile })
84
- : {};
85
-
86
- const result = await validateNextAuth(
87
- identityField,
88
- identity,
89
- protectIdentities,
90
- queryAPI
91
- );
77
+ const userInput = resolver ? await resolver({ user, account, profile }) : {};
78
+
79
+ const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
92
80
  // ID
93
81
  const data: any = {
94
82
  [identityField]: identity,
@@ -97,66 +85,72 @@ export default function NextAuthPage(props: NextAuthPageProps) {
97
85
 
98
86
  if (!result.success) {
99
87
  if (!autoCreate) {
100
- console.log(
101
- '`autoCreate` if set to `false`, skipping user auto-creation'
102
- );
88
+ console.log('`autoCreate` is set to `false`, skipping user auto-creation');
103
89
  return false;
104
90
  }
105
- console.log(
106
- '`autoCreate` if set to `true`, auto-creating a new user'
107
- );
91
+ console.log('`autoCreate` is set to `true`, auto-creating a new user');
108
92
 
109
93
  const createUser = await list
110
94
  .createOne({ data })
111
- .then((returned) => {
112
- console.log('User Created', JSON.stringify(returned));
113
- return true;
95
+ .then(returned => {
96
+ return { success: true, user: returned };
114
97
  })
115
- .catch((error) => {
98
+ .catch(error => {
116
99
  console.log(error);
117
100
  throw new Error(error);
118
101
  });
119
102
  console.log('Created User', createUser);
120
- return createUser;
103
+ return createUser.success;
121
104
  }
122
- // await list.updateOne({where: {id: result.item.id}, data});
123
- return result.success;
105
+ console.log('Data', data);
106
+
107
+ const updateUser = await list
108
+ .updateOne({ where: { id: result.item.id }, data })
109
+ .then(returned => {
110
+ return { success: true, user: returned };
111
+ })
112
+ .catch(error => {
113
+ console.log(error);
114
+ throw new Error(error);
115
+ });
116
+ return updateUser.success;
124
117
  },
125
118
  async redirect({ url }) {
126
119
  return url;
127
120
  },
128
121
  async session({ session, token }) {
129
- const returnSession = {
130
- ...session,
131
- data: token.data,
132
- subject: token.sub,
133
- listKey: token.listKey,
134
- itemId: token.itemId,
135
- };
122
+ let returnSession = session;
123
+ if (!token.itemId) {
124
+ return { expires: '0' };
125
+ } else {
126
+ returnSession = {
127
+ ...session,
128
+ data: token.data,
129
+ subject: token.sub,
130
+ listKey: token.listKey as string,
131
+ itemId: token.itemId as string,
132
+ };
133
+ }
134
+ console.log('Session', returnSession);
135
+
136
136
  return returnSession;
137
137
  },
138
138
  async jwt({ token }) {
139
139
  const identity = token.sub as number | string;
140
- if (!token.itemId) {
141
- const result = await validateNextAuth(
142
- identityField,
143
- identity,
144
- protectIdentities,
145
- queryAPI
146
- );
147
-
148
- if (!result.success) {
149
- return token;
150
- }
140
+ const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
141
+
142
+ if (!result.success) {
143
+ token.itemId = null;
144
+ } else {
151
145
  token.itemId = result.item.id;
146
+ const data = await query[listKey].findOne({
147
+ where: { id: token.itemId },
148
+ query: sessionData || 'id',
149
+ });
150
+ token.data = data;
152
151
  }
153
- const data = await query[listKey].findOne({
154
- where: { id: token.itemId },
155
- query: sessionData || 'id',
156
- });
157
152
  const returnToken = {
158
153
  ...token,
159
- data,
160
154
  subject: token.sub,
161
155
  listKey,
162
156
  };
@@ -167,5 +161,4 @@ export default function NextAuthPage(props: NextAuthPageProps) {
167
161
  });
168
162
  }
169
163
 
170
- export const getNextAuthPage = (props: NextAuthPageProps) => () =>
171
- NextAuthPage({ ...props });
164
+ export const getNextAuthPage = (props: NextAuthPageProps) => () => NextAuthPage({ ...props });
package/src/schema.ts CHANGED
@@ -9,13 +9,11 @@ export const getSchemaExtension = ({
9
9
  identityField: string;
10
10
  listKey: string;
11
11
  }): ExtendGraphqlSchema =>
12
- graphql.extend((base) => {
12
+ graphql.extend(base => {
13
13
  const baseSchema = getBaseAuthSchema({
14
14
  listKey,
15
15
  base,
16
16
  });
17
17
 
18
- return [baseSchema.extension].filter(
19
- (x): x is Exclude<typeof x, undefined> => x !== undefined
20
- );
18
+ return [baseSchema.extension].filter((x): x is Exclude<typeof x, undefined> => x !== undefined);
21
19
  });
@@ -56,11 +56,7 @@ module.exports = withPreconstruct({
56
56
  <% } %>
57
57
  });
58
58
  `;
59
- export const nextConfigTemplate = ({
60
- keystonePath,
61
- }: {
62
- keystonePath: string;
63
- }) => {
59
+ export const nextConfigTemplate = ({ keystonePath }: { keystonePath: string }) => {
64
60
  const nextConfigOut = ejs.render(template, { keystonePath });
65
61
 
66
62
  return nextConfigOut;
@@ -1,8 +1,27 @@
1
- import { BaseListTypeInfo, KeystoneConfig } from '@keystone-6/core/types';
2
- import { CookiesOptions, PagesOptions } from 'next-auth';
1
+ import type { ServerResponse, IncomingMessage } from 'http';
2
+ import type { NextRequest } from 'next/server';
3
3
  import { Provider } from 'next-auth/providers';
4
+ import { CookiesOptions, PagesOptions } from 'next-auth';
5
+ import { BaseListTypeInfo, KeystoneConfig, CreateContext } from '@keystone-6/core/types';
4
6
 
5
- export type NextAuthSession = { listKey: string; itemId: string; data: any };
7
+ type NextAuthResponse = IncomingMessage & NextRequest;
8
+
9
+ export declare type AuthSessionStrategy<StoredSessionData> = {
10
+ start: (args: {
11
+ res: ServerResponse;
12
+ data: any;
13
+ createContext: CreateContext;
14
+ }) => Promise<string>;
15
+ end: (args: {
16
+ req: IncomingMessage;
17
+ res: ServerResponse;
18
+ createContext: CreateContext;
19
+ }) => Promise<void>;
20
+ get: (args: {
21
+ req: NextAuthResponse;
22
+ createContext: CreateContext;
23
+ }) => Promise<StoredSessionData | undefined>;
24
+ };
6
25
 
7
26
  export type NextAuthProviders = Provider[];
8
27
 
@@ -15,9 +34,7 @@ type NextAuthOptions = {
15
34
  resolver: any;
16
35
  };
17
36
 
18
- export type KeystoneOAuthConfig = KeystoneConfig &
19
- KeytoneOAuthOptions &
20
- NextAuthOptions;
37
+ export type KeystoneOAuthConfig = KeystoneConfig & KeytoneOAuthOptions & NextAuthOptions;
21
38
 
22
39
  export type AuthConfig<GeneratedListTypes extends BaseListTypeInfo> = {
23
40
  /** Auth Create users in Keystone DB from Auth Provider */
@@ -31,20 +48,20 @@ export type AuthConfig<GeneratedListTypes extends BaseListTypeInfo> = {
31
48
  /** Path for Keystone interface */
32
49
  keystonePath?: string;
33
50
  // Custom pages for different NextAuth events
34
- pages?: any; // TODO: Fix types
51
+ pages?: Partial<PagesOptions>;
35
52
  /** Providers for Next Auth */
36
53
  providers: NextAuthProviders;
37
54
  /** Resolver for user to define their profile */
38
- resolver?: Function | undefined;
55
+ resolver?: (args: { user: any; profile: any; account: any }) => Promise<{
56
+ [key: string]: boolean | string | number;
57
+ }>;
39
58
  /** Session data population */
40
59
  sessionData?: string | undefined;
41
60
  /** Next-Auth Session Secret */
42
61
  sessionSecret: string;
43
62
  };
44
63
 
45
- export type AuthTokenRequestErrorCode =
46
- | 'IDENTITY_NOT_FOUND'
47
- | 'MULTIPLE_IDENTITY_MATCHES';
64
+ export type AuthTokenRequestErrorCode = 'IDENTITY_NOT_FOUND' | 'MULTIPLE_IDENTITY_MATCHES';
48
65
 
49
66
  export type PasswordAuthErrorCode =
50
67
  | AuthTokenRequestErrorCode
@@ -0,0 +1,19 @@
1
+ import NextAuth from 'next-auth';
2
+ import { JWT } from 'next-auth/jwt';
3
+
4
+ declare module 'next-auth' {
5
+ interface JWT {
6
+ data?: any | undefined;
7
+ subject?: string | undefined;
8
+ listKey?: string;
9
+ itemId?: string | undefined;
10
+ name?: string | null | undefined;
11
+ email?: string | null | undefined;
12
+ picture?: string | null | undefined;
13
+ sub?: string | null | undefined;
14
+ expires?: string | null | undefined;
15
+ }
16
+ interface Session extends JWT {
17
+ user?: any;
18
+ }
19
+ }