@opensaas/keystone-nextjs-auth 20.5.0 → 21.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  import ejs from 'ejs';
2
- import { AuthGqlNames } from '../types';
2
+ import { NextAuthPageProps } from '../pages/NextAuthPage';
3
3
 
4
4
  const template = `
5
5
  import getNextAuthPage from '@opensaas/keystone-nextjs-auth/pages/NextAuthPage';
@@ -7,49 +7,32 @@ import { query } from '.keystone/api';
7
7
  import keystoneConfig from '../../../../../keystone';
8
8
 
9
9
  export default getNextAuthPage({
10
+ autoCreate: <%= autoCreate %>,
10
11
  identityField: '<%= identityField %>',
11
- sessionData: '<%= sessionData %>',
12
12
  listKey: '<%= listKey %>',
13
- userMap: <%- JSON.stringify(userMap) %>,
14
- accountMap: <%- JSON.stringify(accountMap) %>,
15
- profileMap: <%- JSON.stringify(profileMap) %>,
16
- autoCreate: <%= autoCreate %>,
17
- sessionSecret: '<%= sessionSecret %>',
13
+ pages: keystoneConfig.pages,
18
14
  providers: keystoneConfig.providers,
19
15
  query,
16
+ resolver: keystoneConfig.resolver,
17
+ sessionData: '<%= sessionData %>',
18
+ sessionSecret: '<%= sessionSecret %>',
20
19
  });
21
20
  `;
22
21
 
22
+ type AuthTemplateOptions = NextAuthPageProps;
23
+
23
24
  export const authTemplate = ({
24
- gqlNames,
25
+ autoCreate,
25
26
  identityField,
26
- sessionData,
27
27
  listKey,
28
- autoCreate,
29
- userMap,
30
- accountMap,
31
- profileMap,
28
+ sessionData,
32
29
  sessionSecret,
33
- }: {
34
- gqlNames: AuthGqlNames;
35
- identityField: string;
36
- sessionData: any;
37
- listKey: string;
38
- autoCreate: boolean;
39
- userMap: any;
40
- accountMap: any;
41
- profileMap: any;
42
- sessionSecret: string;
43
- }) => {
30
+ }: AuthTemplateOptions) => {
44
31
  const authOut = ejs.render(template, {
45
- gqlNames,
46
32
  identityField,
47
33
  sessionData,
48
34
  listKey,
49
35
  autoCreate,
50
- userMap,
51
- accountMap,
52
- profileMap,
53
36
  sessionSecret,
54
37
  });
55
38
  return authOut;
@@ -9,6 +9,9 @@ module.exports = withPreconstruct({
9
9
  typescript: {
10
10
  ignoreBuildErrors: true,
11
11
  },
12
+ env: {
13
+ NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'http://localhost:<%= process.env.PORT || 3000 %><%= keystonePath || '' %>/api/auth',
14
+ },
12
15
  eslint: {
13
16
  ignoreDuringBuilds: true,
14
17
  },
package/src/types.ts CHANGED
@@ -1,44 +1,43 @@
1
1
  import { BaseListTypeInfo, KeystoneConfig } from '@keystone-6/core/types';
2
+ import { CookiesOptions, PagesOptions } from 'next-auth';
2
3
  import { Provider } from 'next-auth/providers';
3
4
 
4
- export type AuthGqlNames = {
5
- CreateInitialInput: string;
6
- createInitialItem: string;
7
- authenticateItemWithPassword: string;
8
- ItemAuthenticationWithPasswordResult: string;
9
- ItemAuthenticationWithPasswordSuccess: string;
10
- ItemAuthenticationWithPasswordFailure: string;
11
- };
12
-
13
5
  export type NextAuthSession = { listKey: string; itemId: string; data: any };
14
6
 
15
7
  export type NextAuthProviders = Provider[];
16
8
 
17
- type KeytoneAuthProviders = {
9
+ type KeytoneOAuthOptions = {
18
10
  providers: NextAuthProviders;
11
+ pages?: Partial<PagesOptions>;
12
+ };
13
+ type NextAuthOptions = {
14
+ cookies?: Partial<CookiesOptions>;
15
+ resolver: any;
19
16
  };
20
17
 
21
- export type KeystoneAuthConfig = KeystoneConfig & KeytoneAuthProviders;
18
+ export type KeystoneOAuthConfig = KeystoneConfig &
19
+ KeytoneOAuthOptions &
20
+ NextAuthOptions;
22
21
 
23
22
  export type AuthConfig<GeneratedListTypes extends BaseListTypeInfo> = {
23
+ /** Auth Create users in Keystone DB from Auth Provider */
24
+ autoCreate: boolean;
25
+ /** Adds ability to customize cookie options, for example, to facilitate cross-subdomain functionality */
26
+ cookies?: Partial<CookiesOptions>;
24
27
  /** The key of the list to authenticate users with */
25
28
  listKey: GeneratedListTypes['key'];
26
29
  /** The path of the field the identity is stored in; must be text-ish */
27
30
  identityField: GeneratedListTypes['fields'];
28
- /** Session data population */
29
- sessionData?: string;
30
- /** Auth Create users in Keystone DB from Auth Provider */
31
- autoCreate: boolean;
32
- /** Map User in next-auth to item */
33
- userMap: any;
34
- /** Map Account in next-auth to item */
35
- accountMap: any;
36
- /** Map Profile in next-auth to item */
37
- profileMap: any;
38
31
  /** Path for Keystone interface */
39
32
  keystonePath?: string;
33
+ // Custom pages for different NextAuth events
34
+ pages?: any; // TODO: Fix types
40
35
  /** Providers for Next Auth */
41
36
  providers: NextAuthProviders;
37
+ /** Resolver for user to define their profile */
38
+ resolver?: Function | undefined;
39
+ /** Session data population */
40
+ sessionData?: string | undefined;
42
41
  /** Next-Auth Session Secret */
43
42
  sessionSecret: string;
44
43
  };
@@ -1,81 +0,0 @@
1
- import type {
2
- GraphQLSchemaExtension,
3
- KeystoneContext,
4
- } from '@keystone-6/core/types';
5
- import {
6
- assertInputObjectType,
7
- GraphQLInputObjectType,
8
- GraphQLSchema,
9
- printType,
10
- } from 'graphql';
11
-
12
- import { AuthGqlNames, InitFirstItemConfig } from '../types';
13
-
14
- export function getInitFirstItemSchema({
15
- listKey,
16
- fields,
17
- itemData,
18
- gqlNames,
19
- graphQLSchema,
20
- }: {
21
- listKey: string;
22
- fields: InitFirstItemConfig<any>['fields'];
23
- itemData: InitFirstItemConfig<any>['itemData'];
24
- gqlNames: AuthGqlNames;
25
- graphQLSchema: GraphQLSchema;
26
- }): GraphQLSchemaExtension {
27
- const createInputConfig = assertInputObjectType(
28
- graphQLSchema.getType(`${listKey}CreateInput`)
29
- ).toConfig();
30
- const fieldsSet = new Set<any>(fields);
31
- const initialCreateInput = printType(
32
- new GraphQLInputObjectType({
33
- ...createInputConfig,
34
- fields: Object.fromEntries(
35
- Object.entries(createInputConfig.fields).filter(([fieldKey]) =>
36
- fieldsSet.has(fieldKey)
37
- )
38
- ),
39
- name: gqlNames.CreateInitialInput,
40
- })
41
- );
42
- return {
43
- typeDefs: `
44
- ${initialCreateInput}
45
- type Mutation {
46
- ${gqlNames.createInitialItem}(data: ${gqlNames.CreateInitialInput}!): ${gqlNames.ItemAuthenticationWithPasswordSuccess}!
47
- }
48
- `,
49
- resolvers: {
50
- Mutation: {
51
- async [gqlNames.createInitialItem](
52
- root: any,
53
- { data }: { data: Record<string, any> },
54
- context: KeystoneContext
55
- ) {
56
- if (!context.startSession) {
57
- throw new Error('No session implementation available on context');
58
- }
59
-
60
- const dbItemAPI = context.sudo().db[listKey];
61
- const count = await dbItemAPI.count({});
62
- if (count !== 0) {
63
- throw new Error(
64
- 'Initial items can only be created when no items exist in that list'
65
- );
66
- }
67
-
68
- // Update system state
69
- const item = await dbItemAPI.createOne({
70
- data: { ...data, ...itemData },
71
- });
72
- const sessionToken = await context.startSession({
73
- listKey,
74
- itemId: item.id,
75
- });
76
- return { item, sessionToken };
77
- },
78
- },
79
- },
80
- };
81
- }