Skip to content

Commit 612431b

Browse files
authored
Add Session type parameter for TypeInfo, Lists and Context (#8570)
Co-authored-by: Daniel Cousens <dcousens@users.noreply.github.com>
1 parent b8453c6 commit 612431b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2014
-1412
lines changed

.changeset/add-cookie-name.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@keystone-6/core': minor
3+
---
4+
5+
Adds `cookieName` as an option for `statelessSessions`

.changeset/more-session-types.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@keystone-6/core': minor
3+
---
4+
5+
Adds `Session` type parameter to generated `TypeInfo`, `Lists` and `Context` types, and propagates that type to access control and hooks

examples/auth/keystone.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ const sessionMaxAge = 60 * 60 * 24 * 30;
1818

1919
// withAuth is a function we can use to wrap our base configuration
2020
const { withAuth } = createAuth({
21-
// this is the list that contains items people can sign in as
21+
// this is the list that contains our users
2222
listKey: 'User',
2323

24-
// an identity field is typically a username or email address
25-
identityField: 'email',
24+
// an identity field, typically a username or an email address
25+
identityField: 'name',
2626

27-
// a secret field must be a password type field
27+
// a secret field must be a password field type
2828
secretField: 'password',
2929

3030
// initFirstItem enables the "First User" experience, this will add an interface form
@@ -34,7 +34,7 @@ const { withAuth } = createAuth({
3434
// see https://keystonejs.com/docs/config/auth#init-first-item for more
3535
initFirstItem: {
3636
// the following fields are used by the "Create First User" form
37-
fields: ['name', 'email', 'password'],
37+
fields: ['name', 'password'],
3838

3939
// the following fields are configured by default for this item
4040
itemData: {
@@ -43,18 +43,10 @@ const { withAuth } = createAuth({
4343
},
4444
},
4545

46-
// add isAdmin to the session data(required by isAccessAllowed)
46+
// add isAdmin to the session data
4747
sessionData: 'isAdmin',
4848
});
4949

50-
// you can find out more at https://keystonejs.com/docs/apis/session#session-api
51-
const session = statelessSessions({
52-
// an maxAge option controls how long session cookies are valid for before they expire
53-
maxAge: sessionMaxAge,
54-
// an session secret is used to encrypt cookie data (should be an environment variable)
55-
secret: sessionSecret,
56-
});
57-
5850
export default withAuth(
5951
config({
6052
db: {
@@ -65,12 +57,18 @@ export default withAuth(
6557
...fixPrismaPath,
6658
},
6759
lists,
68-
session,
6960
ui: {
7061
// only admins can view the AdminUI
7162
isAccessAllowed: ({ session }) => {
72-
return session?.data?.isAdmin;
63+
return session?.data?.isAdmin ?? false;
7364
},
7465
},
66+
// you can find out more at https://keystonejs.com/docs/apis/session#session-api
67+
session: statelessSessions({
68+
// the maxAge option controls how long session cookies are valid for before they expire
69+
maxAge: sessionMaxAge,
70+
// the session secret is used to encrypt cookie data
71+
secret: sessionSecret,
72+
}),
7573
})
7674
);

examples/auth/schema.graphql

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
type User {
55
id: ID!
66
name: String
7-
email: String
87
password: PasswordState
98
isAdmin: Boolean
109
}
@@ -22,8 +21,6 @@ input UserWhereInput {
2221
OR: [UserWhereInput!]
2322
NOT: [UserWhereInput!]
2423
id: IDFilter
25-
name: StringFilter
26-
password: PasswordFilter
2724
isAdmin: BooleanFilter
2825
}
2926

@@ -38,46 +35,13 @@ input IDFilter {
3835
not: IDFilter
3936
}
4037

41-
input StringFilter {
42-
equals: String
43-
in: [String!]
44-
notIn: [String!]
45-
lt: String
46-
lte: String
47-
gt: String
48-
gte: String
49-
contains: String
50-
startsWith: String
51-
endsWith: String
52-
not: NestedStringFilter
53-
}
54-
55-
input NestedStringFilter {
56-
equals: String
57-
in: [String!]
58-
notIn: [String!]
59-
lt: String
60-
lte: String
61-
gt: String
62-
gte: String
63-
contains: String
64-
startsWith: String
65-
endsWith: String
66-
not: NestedStringFilter
67-
}
68-
69-
input PasswordFilter {
70-
isSet: Boolean!
71-
}
72-
7338
input BooleanFilter {
7439
equals: Boolean
7540
not: BooleanFilter
7641
}
7742

7843
input UserOrderByInput {
7944
id: OrderDirection
80-
name: OrderDirection
8145
isAdmin: OrderDirection
8246
}
8347

@@ -88,7 +52,6 @@ enum OrderDirection {
8852

8953
input UserUpdateInput {
9054
name: String
91-
email: String
9255
password: String
9356
isAdmin: Boolean
9457
}
@@ -100,7 +63,6 @@ input UserUpdateArgs {
10063

10164
input UserCreateInput {
10265
name: String
103-
email: String
10466
password: String
10567
isAdmin: Boolean
10668
}
@@ -118,7 +80,7 @@ type Mutation {
11880
deleteUser(where: UserWhereUniqueInput!): User
11981
deleteUsers(where: [UserWhereUniqueInput!]!): [User]
12082
endSession: Boolean!
121-
authenticateUserWithPassword(email: String!, password: String!): UserAuthenticationWithPasswordResult
83+
authenticateUserWithPassword(name: String!, password: String!): UserAuthenticationWithPasswordResult
12284
createInitialUser(data: CreateInitialUserInput!): UserAuthenticationWithPasswordSuccess!
12385
}
12486

@@ -135,7 +97,6 @@ type UserAuthenticationWithPasswordFailure {
13597

13698
input CreateInitialUserInput {
13799
name: String
138-
email: String
139100
password: String
140101
}
141102

examples/auth/schema.prisma

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ generator client {
1414

1515
model User {
1616
id String @id @default(cuid())
17-
name String @default("")
18-
email String @unique @default("")
19-
password String?
17+
name String @unique @default("")
18+
password String
2019
isAdmin Boolean @default(false)
2120
}

examples/auth/schema.ts

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { list } from '@keystone-6/core';
2-
import { allowAll } from '@keystone-6/core/access';
2+
import { allowAll, denyAll } from '@keystone-6/core/access';
33
import { text, checkbox, password } from '@keystone-6/core/fields';
44
import type { Lists } from '.keystone/types';
55

@@ -14,17 +14,11 @@ type Session = {
1414
};
1515
};
1616

17-
function hasSession({ session }: { session: Session | undefined }) {
17+
function hasSession({ session }: { session?: Session }) {
1818
return Boolean(session);
1919
}
2020

21-
function isAdminOrSameUser({
22-
session,
23-
item,
24-
}: {
25-
session: Session | undefined;
26-
item: Lists.User.Item;
27-
}) {
21+
function isAdminOrSameUser({ session, item }: { session?: Session; item: Lists.User.Item }) {
2822
// you need to have a session to do this
2923
if (!session) return false;
3024

@@ -35,7 +29,7 @@ function isAdminOrSameUser({
3529
return session.itemId === item.id;
3630
}
3731

38-
function isAdminOrSameUserFilter({ session }: { session: Session | undefined }) {
32+
function isAdminOrSameUserFilter({ session }: { session?: Session }) {
3933
// you need to have a session to do this
4034
if (!session) return false;
4135

@@ -50,7 +44,7 @@ function isAdminOrSameUserFilter({ session }: { session: Session | undefined })
5044
};
5145
}
5246

53-
function isAdmin({ session }: { session: Session | undefined }) {
47+
function isAdmin({ session }: { session?: Session }) {
5448
// you need to have a session to do this
5549
if (!session) return false;
5650

@@ -89,18 +83,16 @@ export const lists: Lists = {
8983
hideDelete: args => !isAdmin(args),
9084
listView: {
9185
// the default columns that will be displayed in the list view
92-
initialColumns: ['name', 'email', 'isAdmin'],
86+
initialColumns: ['name', 'isAdmin'],
9387
},
9488
},
9589
fields: {
96-
// the user's name, publicly visible
97-
name: text({ validation: { isRequired: true } }),
98-
99-
// the user's email address, used as the identity field for authentication
90+
// the user's name, used as the identity field for authentication
10091
// should not be publicly visible
10192
//
102-
// we use isIndexed to enforce this email is unique
103-
email: text({
93+
// we use isIndexed to enforce names are unique
94+
// that may not suitable for your application
95+
name: text({
10496
access: {
10597
// only the respective user, or an admin can read this field
10698
read: isAdminOrSameUser,
@@ -120,17 +112,19 @@ export const lists: Lists = {
120112
// should not be publicly visible
121113
password: password({
122114
access: {
123-
read: isAdminOrSameUser, // TODO: is this required?
115+
read: denyAll, // TODO: is this required?
124116
update: isAdminOrSameUser,
125117
},
118+
validation: {
119+
isRequired: true,
120+
},
126121
ui: {
127122
itemView: {
128123
// don't show this field if it isn't relevant
129124
fieldMode: args => (isAdminOrSameUser(args) ? 'edit' : 'hidden'),
130125
},
131126
listView: {
132-
// TODO: ?
133-
fieldMode: args => (isAdmin(args) ? 'read' : 'hidden'),
127+
fieldMode: 'hidden', // TODO: is this required?
134128
},
135129
},
136130
}),

examples/custom-output-paths/my-types.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ type ResolvedPostUpdateInput = {
147147
};
148148

149149
export declare namespace Lists {
150-
export type Post = import('@keystone-6/core').ListConfig<Lists.Post.TypeInfo, any>;
150+
export type Post<Session = any> = import('@keystone-6/core').ListConfig<Lists.Post.TypeInfo<Session>, any>;
151151
namespace Post {
152152
export type Item = import('./node_modules/.myprisma/client').Post;
153-
export type TypeInfo = {
153+
export type TypeInfo<Session = any> = {
154154
key: 'Post';
155155
isSingleton: false;
156156
fields: 'id' | 'title' | 'content' | 'publishDate'
@@ -166,23 +166,25 @@ export declare namespace Lists {
166166
create: ResolvedPostCreateInput;
167167
update: ResolvedPostUpdateInput;
168168
};
169-
all: __TypeInfo;
169+
all: __TypeInfo<Session>;
170170
};
171171
}
172172
}
173-
export type Context = import('@keystone-6/core/types').KeystoneContext<TypeInfo>;
173+
export type Context<Session = any> = import('@keystone-6/core/types').KeystoneContext<TypeInfo<Session>>;
174+
export type Config<Session = any> = import('@keystone-6/core/types').KeystoneConfig<TypeInfo<Session>>;
174175

175-
export type TypeInfo = {
176+
export type TypeInfo<Session = any> = {
176177
lists: {
177178
readonly Post: Lists.Post.TypeInfo;
178179
};
179180
prisma: import('./node_modules/.myprisma/client').PrismaClient;
181+
session: Session;
180182
};
181183

182-
type __TypeInfo = TypeInfo;
184+
type __TypeInfo<Session = any> = TypeInfo<Session>;
183185

184-
export type Lists = {
185-
[Key in keyof TypeInfo['lists']]?: import('@keystone-6/core').ListConfig<TypeInfo['lists'][Key], any>
186+
export type Lists<Session = any> = {
187+
[Key in keyof TypeInfo['lists']]?: import('@keystone-6/core').ListConfig<TypeInfo<Session>['lists'][Key], any>
186188
} & Record<string, import('@keystone-6/core').ListConfig<any, any>>;
187189

188190
export {}
File renamed without changes.

0 commit comments

Comments
 (0)