@opensaas/keystone-nextjs-auth 15.0.0 → 18.0.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.
- package/CHANGELOG.md +24 -0
- package/dist/declarations/src/gql/getBaseAuthSchema.d.ts +14 -6
- package/dist/declarations/src/index.d.ts +12 -12
- package/dist/declarations/src/lib/findMatchingIdentity.d.ts +8 -8
- package/dist/declarations/src/lib/validateNextAuth.d.ts +12 -12
- package/dist/declarations/src/pages/NextAuthPage.d.ts +17 -17
- package/dist/declarations/src/schema.d.ts +7 -7
- package/dist/declarations/src/templates/auth.d.ts +11 -11
- package/dist/declarations/src/templates/next-config.d.ts +3 -3
- package/dist/declarations/src/types.d.ts +45 -53
- package/dist/opensaas-keystone-nextjs-auth.cjs.dev.js +85 -80
- package/dist/opensaas-keystone-nextjs-auth.cjs.prod.js +85 -80
- package/dist/opensaas-keystone-nextjs-auth.esm.js +72 -64
- package/package.json +7 -7
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.dev.js +6 -11
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.prod.js +6 -11
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.esm.js +4 -9
- package/src/gql/getBaseAuthSchema.ts +20 -39
- package/src/index.ts +6 -5
- package/src/lib/findMatchingIdentity.ts +0 -3
- package/src/pages/NextAuthPage.tsx +2 -5
- package/src/schema.ts +37 -22
- package/src/templates/auth.ts +0 -2
- package/src/templates/next-config.ts +20 -0
- package/src/types.ts +0 -11
package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.prod.js
CHANGED
@@ -13,10 +13,8 @@ async function findMatchingIdentity(identityField, identity, queryAPI) {
|
|
13
13
|
const item = await queryAPI.findOne({
|
14
14
|
where: {
|
15
15
|
[identityField]: identity
|
16
|
-
}
|
17
|
-
|
18
|
-
});
|
19
|
-
console.log(item); // Identity failures with helpful errors
|
16
|
+
}
|
17
|
+
}); // Identity failures with helpful errors
|
20
18
|
|
21
19
|
let code;
|
22
20
|
|
@@ -71,7 +69,7 @@ function NextAuthPage(props) {
|
|
71
69
|
const list = query[listKey];
|
72
70
|
const queryAPI = query[listKey];
|
73
71
|
const protectIdentities = true;
|
74
|
-
return NextAuth__default[
|
72
|
+
return NextAuth__default["default"]({
|
75
73
|
providers,
|
76
74
|
callbacks: {
|
77
75
|
async signIn(user, account, profile) {
|
@@ -128,13 +126,11 @@ function NextAuthPage(props) {
|
|
128
126
|
}
|
129
127
|
},
|
130
128
|
|
131
|
-
async redirect(url
|
129
|
+
async redirect(url) {
|
132
130
|
return url;
|
133
131
|
},
|
134
132
|
|
135
133
|
async session(session, token) {
|
136
|
-
console.log('session:', session);
|
137
|
-
|
138
134
|
const returnSession = _objectSpread(_objectSpread({}, session), {}, {
|
139
135
|
data: token.data,
|
140
136
|
subject: token.sub,
|
@@ -145,8 +141,7 @@ function NextAuthPage(props) {
|
|
145
141
|
return returnSession;
|
146
142
|
},
|
147
143
|
|
148
|
-
async jwt(token
|
149
|
-
console.log('account:', account);
|
144
|
+
async jwt(token) {
|
150
145
|
const identity = token.sub;
|
151
146
|
|
152
147
|
if (!token.itemId) {
|
@@ -181,5 +176,5 @@ function NextAuthPage(props) {
|
|
181
176
|
}
|
182
177
|
const getNextAuthPage = props => () => NextAuthPage(_objectSpread({}, props));
|
183
178
|
|
184
|
-
exports[
|
179
|
+
exports["default"] = NextAuthPage;
|
185
180
|
exports.getNextAuthPage = getNextAuthPage;
|
@@ -5,10 +5,8 @@ async function findMatchingIdentity(identityField, identity, queryAPI) {
|
|
5
5
|
const item = await queryAPI.findOne({
|
6
6
|
where: {
|
7
7
|
[identityField]: identity
|
8
|
-
}
|
9
|
-
|
10
|
-
});
|
11
|
-
console.log(item); // Identity failures with helpful errors
|
8
|
+
}
|
9
|
+
}); // Identity failures with helpful errors
|
12
10
|
|
13
11
|
let code;
|
14
12
|
|
@@ -120,13 +118,11 @@ function NextAuthPage(props) {
|
|
120
118
|
}
|
121
119
|
},
|
122
120
|
|
123
|
-
async redirect(url
|
121
|
+
async redirect(url) {
|
124
122
|
return url;
|
125
123
|
},
|
126
124
|
|
127
125
|
async session(session, token) {
|
128
|
-
console.log('session:', session);
|
129
|
-
|
130
126
|
const returnSession = _objectSpread(_objectSpread({}, session), {}, {
|
131
127
|
data: token.data,
|
132
128
|
subject: token.sub,
|
@@ -137,8 +133,7 @@ function NextAuthPage(props) {
|
|
137
133
|
return returnSession;
|
138
134
|
},
|
139
135
|
|
140
|
-
async jwt(token
|
141
|
-
console.log('account:', account);
|
136
|
+
async jwt(token) {
|
142
137
|
const identity = token.sub;
|
143
138
|
|
144
139
|
if (!token.itemId) {
|
@@ -1,57 +1,38 @@
|
|
1
|
-
import type {
|
2
|
-
|
3
|
-
KeystoneContext,
|
4
|
-
} from '@keystone-next/keystone/types';
|
1
|
+
import type { ItemRootValue } from '@keystone-next/keystone/types';
|
2
|
+
import { graphql } from '@keystone-next/keystone';
|
5
3
|
|
6
4
|
import { AuthGqlNames } from '../types';
|
7
5
|
|
8
|
-
export function getBaseAuthSchema
|
6
|
+
export function getBaseAuthSchema({
|
9
7
|
listKey,
|
10
8
|
gqlNames,
|
9
|
+
base,
|
11
10
|
}: {
|
12
11
|
listKey: string;
|
13
12
|
gqlNames: AuthGqlNames;
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
async authenticatedItem(root, args, { session, query }: KeystoneContext) {
|
13
|
+
base: graphql.BaseSchemaMeta;
|
14
|
+
}) {
|
15
|
+
const extension = {
|
16
|
+
query: {
|
17
|
+
authenticatedItem: graphql.field({
|
18
|
+
type: graphql.union({
|
19
|
+
name: 'AuthenticatedItem',
|
20
|
+
types: [base.object(listKey) as graphql.ObjectType<ItemRootValue>],
|
21
|
+
resolveType: (root, context) => context.session?.listKey,
|
22
|
+
}),
|
23
|
+
resolve(root, args, { session, db }) {
|
26
24
|
if (
|
27
25
|
typeof session?.itemId === 'string' &&
|
28
26
|
typeof session.listKey === 'string'
|
29
27
|
) {
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
resolveFields: false,
|
34
|
-
});
|
35
|
-
} catch (e) {
|
36
|
-
return null;
|
37
|
-
}
|
28
|
+
return db[session.listKey].findOne({
|
29
|
+
where: { id: session.itemId },
|
30
|
+
});
|
38
31
|
}
|
39
32
|
return null;
|
40
33
|
},
|
41
|
-
},
|
42
|
-
AuthenticatedItem: {
|
43
|
-
__resolveType(rootVal: any, { session }: KeystoneContext) {
|
44
|
-
return session?.listKey;
|
45
|
-
},
|
46
|
-
},
|
47
|
-
// TODO: Is this the preferred approach for this?
|
48
|
-
[gqlNames.ItemAuthenticationWithPasswordResult]: {
|
49
|
-
__resolveType(rootVal: any) {
|
50
|
-
return rootVal.sessionToken
|
51
|
-
? gqlNames.ItemAuthenticationWithPasswordSuccess
|
52
|
-
: gqlNames.ItemAuthenticationWithPasswordFailure;
|
53
|
-
},
|
54
|
-
},
|
34
|
+
}),
|
55
35
|
},
|
56
36
|
};
|
37
|
+
return { extension };
|
57
38
|
}
|
package/src/index.ts
CHANGED
@@ -236,7 +236,7 @@ export function createAuth<GeneratedListTypes extends BaseGeneratedListTypes>({
|
|
236
236
|
...keystoneConfig.ui,
|
237
237
|
publicPages: [...(keystoneConfig.ui.publicPages || []), ...publicPages],
|
238
238
|
getAdditionalFiles: [
|
239
|
-
...(keystoneConfig.ui
|
239
|
+
...(keystoneConfig.ui?.getAdditionalFiles || []),
|
240
240
|
getAdditionalFiles,
|
241
241
|
],
|
242
242
|
pageMiddleware: async (args) =>
|
@@ -266,10 +266,11 @@ export function createAuth<GeneratedListTypes extends BaseGeneratedListTypes>({
|
|
266
266
|
},
|
267
267
|
};
|
268
268
|
}
|
269
|
-
|
270
|
-
if (session
|
271
|
-
|
272
|
-
|
269
|
+
|
270
|
+
if (!keystoneConfig.session)
|
271
|
+
throw new TypeError('Missing .session configuration');
|
272
|
+
const session = withItemData(keystoneConfig.session);
|
273
|
+
|
273
274
|
const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
|
274
275
|
return {
|
275
276
|
...keystoneConfig,
|
@@ -10,10 +10,7 @@ export async function findMatchingIdentity(
|
|
10
10
|
> {
|
11
11
|
const item = await queryAPI.findOne({
|
12
12
|
where: { [identityField]: identity },
|
13
|
-
resolveFields: false,
|
14
13
|
});
|
15
|
-
console.log(item);
|
16
|
-
|
17
14
|
// Identity failures with helpful errors
|
18
15
|
let code: AuthTokenRequestErrorCode | undefined;
|
19
16
|
if (!item) {
|
@@ -94,11 +94,10 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
94
94
|
return result.success;
|
95
95
|
}
|
96
96
|
},
|
97
|
-
async redirect(url
|
97
|
+
async redirect(url) {
|
98
98
|
return url;
|
99
99
|
},
|
100
100
|
async session(session: any, token: any) {
|
101
|
-
console.log('session:', session);
|
102
101
|
const returnSession = {
|
103
102
|
...session,
|
104
103
|
data: token.data,
|
@@ -108,9 +107,7 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
108
107
|
};
|
109
108
|
return returnSession;
|
110
109
|
},
|
111
|
-
async jwt(token
|
112
|
-
console.log('account:', account);
|
113
|
-
|
110
|
+
async jwt(token) {
|
114
111
|
const identity = token.sub;
|
115
112
|
if (!token.itemId) {
|
116
113
|
const result = await validateNextAuth(
|
package/src/schema.ts
CHANGED
@@ -1,28 +1,43 @@
|
|
1
|
-
import { mergeSchemas } from '@graphql-tools/merge';
|
2
1
|
import { ExtendGraphqlSchema } from '@keystone-next/keystone/types';
|
3
2
|
|
3
|
+
import { assertInputObjectType, GraphQLString, GraphQLID } from 'graphql';
|
4
|
+
import { graphql } from '@keystone-next/keystone';
|
4
5
|
import { AuthGqlNames } from './types';
|
5
6
|
import { getBaseAuthSchema } from './gql/getBaseAuthSchema';
|
6
7
|
|
7
|
-
export const getSchemaExtension =
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
8
|
+
export const getSchemaExtension = ({
|
9
|
+
identityField,
|
10
|
+
listKey,
|
11
|
+
gqlNames,
|
12
|
+
}: {
|
13
|
+
identityField: string;
|
14
|
+
listKey: string;
|
15
|
+
gqlNames: AuthGqlNames;
|
16
|
+
}): ExtendGraphqlSchema =>
|
17
|
+
graphql.extend((base) => {
|
18
|
+
const uniqueWhereInputType = assertInputObjectType(
|
19
|
+
base.schema.getType(`${listKey}WhereUniqueInput`)
|
20
|
+
);
|
21
|
+
const identityFieldOnUniqueWhere =
|
22
|
+
uniqueWhereInputType.getFields()[identityField];
|
23
|
+
if (
|
24
|
+
identityFieldOnUniqueWhere?.type !== GraphQLString &&
|
25
|
+
identityFieldOnUniqueWhere?.type !== GraphQLID
|
26
|
+
) {
|
27
|
+
throw new Error(
|
28
|
+
`createAuth was called with an identityField of ${identityField} on the list ${listKey} ` +
|
29
|
+
`but that field doesn't allow being searched uniquely with a String or ID. ` +
|
30
|
+
`You should likely add \`isIndexed: 'unique'\` ` +
|
31
|
+
`to the field at ${listKey}.${identityField}`
|
28
32
|
);
|
33
|
+
}
|
34
|
+
const baseSchema = getBaseAuthSchema({
|
35
|
+
listKey,
|
36
|
+
gqlNames,
|
37
|
+
base,
|
38
|
+
});
|
39
|
+
|
40
|
+
return [baseSchema.extension].filter(
|
41
|
+
(x): x is Exclude<typeof x, undefined> => x !== undefined
|
42
|
+
);
|
43
|
+
});
|
package/src/templates/auth.ts
CHANGED
@@ -3,13 +3,11 @@ import { AuthGqlNames } from '../types';
|
|
3
3
|
|
4
4
|
const template = `
|
5
5
|
import getNextAuthPage from '@opensaas/keystone-nextjs-auth/pages/NextAuthPage';
|
6
|
-
import { nextAuthProviders as Providers } from '@opensaas/keystone-nextjs-auth';
|
7
6
|
import { query } from '.keystone/api';
|
8
7
|
import keystoneConfig from '../../../../../keystone';
|
9
8
|
|
10
9
|
export default getNextAuthPage({
|
11
10
|
identityField: '<%= identityField %>',
|
12
|
-
mutationName: '<%= gqlNames.authenticateItemWithPassword %>',
|
13
11
|
sessionData: '<%= sessionData %>',
|
14
12
|
listKey: '<%= listKey %>',
|
15
13
|
userMap: <%- JSON.stringify(userMap) %>,
|
@@ -27,10 +27,30 @@ module.exports = withPreconstruct({
|
|
27
27
|
/@keystone-next\\/keystone(?!\\/___internal-do-not-use-will-break-in-patch\\/admin-ui\\/id-field-view|\\/fields\\/types\\/[^\\/]+\\/views)/,
|
28
28
|
/.prisma\\/client/
|
29
29
|
];
|
30
|
+
// we need to set these to true so that when __dirname/__filename is used
|
31
|
+
// to resolve the location of field views, we will get a path that we can use
|
32
|
+
// rather than just the __dirname/__filename of the generated file.
|
33
|
+
// https://webpack.js.org/configuration/node/#node__filename
|
34
|
+
(_config$node = config.node) !== null && _config$node !== void 0 ? _config$node : config.node = {};
|
35
|
+
config.node.__dirname = true;
|
36
|
+
config.node.__filename = true;
|
30
37
|
}
|
31
38
|
return config;
|
32
39
|
},
|
40
|
+
<% if (keystonePath) { %>
|
41
|
+
<% if (process.env.NODE_ENV != 'production') { %>
|
42
|
+
async rewrites() {
|
43
|
+
return [
|
44
|
+
{
|
45
|
+
source: '/api/__keystone_api_build',
|
46
|
+
destination: 'http://localhost:3000<%= keystonePath || '' %>/api/__keystone_api_build',
|
47
|
+
basePath: false
|
48
|
+
}
|
49
|
+
];
|
50
|
+
},
|
51
|
+
<% }%>
|
33
52
|
basePath: '<%= keystonePath || '' %>'
|
53
|
+
<% } %>
|
34
54
|
});
|
35
55
|
`;
|
36
56
|
export const nextConfigTemplate = ({
|
package/src/types.ts
CHANGED
@@ -44,17 +44,6 @@ export type AuthConfig<GeneratedListTypes extends BaseGeneratedListTypes> = {
|
|
44
44
|
providers: NextAuthProviders;
|
45
45
|
};
|
46
46
|
|
47
|
-
export type InitFirstItemConfig<
|
48
|
-
GeneratedListTypes extends BaseGeneratedListTypes
|
49
|
-
> = {
|
50
|
-
/** Array of fields to collect, e.g ['name', 'email', 'password'] */
|
51
|
-
fields: GeneratedListTypes['fields'][];
|
52
|
-
/** Suppresses the second screen where we ask people to subscribe and follow Keystone */
|
53
|
-
skipKeystoneWelcome?: boolean;
|
54
|
-
/** Extra input to add for the create mutation */
|
55
|
-
itemData?: Partial<GeneratedListTypes['inputs']['create']>;
|
56
|
-
};
|
57
|
-
|
58
47
|
export type AuthTokenRequestErrorCode =
|
59
48
|
| 'IDENTITY_NOT_FOUND'
|
60
49
|
| 'MULTIPLE_IDENTITY_MATCHES';
|