Repository navigation
Expand file tree
/
Copy pathschema.ts
More file actions
232 lines (228 loc) · 8.94 KB
/
Copy pathschema.ts
File metadata and controls
232 lines (228 loc) · 8.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
2
10BC8
24
225
226
227
228
229
230
231
232
import { list } from '@keystone-6/core';
import { allOperations } from '@keystone-6/core/access';
import { checkbox, password, relationship, text } from '@keystone-6/core/fields';
import { isSignedIn, permissions, rules } from './access';
/*
The set of permissions a role could have would change based on application requirements, so the
checkboxes in the Role list below are fairly arbitary to demonstrate the idea.
The default permissions (not assigned with roles) in this example are:
- All users can sign into the Admin UI
- All users can see and manage todo items assigned to themselves
*/
export const lists = {
Todo: list({
/*
SPEC
- [x] Block all public access
- [x] Restrict list create based on canCreateTodos
- [x] Restrict list read based on canManageAllTodos and isPrivate
- [x] Users without canManageAllTodos can only see their own todo items
- [x] Users can never see todo items with isPrivate unless assigned to themselves
- [x] Restrict list update / delete based on canManageAllTodos
- [x] Users can always update / delete their own todo items
- [x] Users can only update / delete todo items assigned to other people with canManageAllTodos
- [ ] Validate assignment on create based on canManageAllTodos
- [ ] Users without canManageAllTodos can only create Todos assigned to themselves
- [ ] Users with canManageAllTodos can create and assign Todos to anyone
- [ ] Nobody can create private users assigned to another user
- [ ] Extend the Admin UI to stop people creating private Todos assigned to someone else
*/
access: {
operation: {
...allOperations(isSignedIn),
create: permissions.canCreateTodos,
},
filter: {
query: rules.canReadTodos,
update: rules.canManageTodos,
delete: rules.canManageTodos,
},
},
ui: {
hideCreate: args => !permissions.canCreateTodos(args),
listView: {
initialColumns: ['label', 'isComplete', 'assignedTo'],
},
},
fields: {
/* The label of the todo item */
label: text({ validation: { isRequired: true } }),
/* Whether the todo item is complete */
isComplete: checkbox({ defaultValue: false }),
/* Private todo items are only visible to the user they are assigned to */
isPrivate: checkbox({ defaultValue: false }),
/* The person the todo item is assigned to */
assignedTo: relationship({
ref: 'Person.tasks',
ui: {
createView: {
fieldMode: args => (permissions.canManageAllTodos(args) ? 'edit' : 'hidden'),
},
itemView: {
fieldMode: args => (permissions.canManageAllTodos(args) ? 'edit' : 'read'),
},
},
hooks: {
resolveInput({ operation, resolvedData, context }) {
if (operation === 'create' && !resolvedData.assignedTo) {
// Always default new todo items to the current user; this is important because users
// without canManageAllTodos don't see this field when creating new items
return { connect: { id: context.session.itemId } };
}
return resolvedData.assignedTo;
},
},
}),
},
}),
Person: list({
/*
SPEC
- [x] Block all public access
- [x] Restrict list create based on canManagePeople
- [x] Restrict list read based on canSeeOtherPeople
- [x] Restrict list update based on canEditOtherPeople
- [x] Restrict list delete based on canManagePeople
- [x] Restrict role field update based on canManagePeople
- [x] Restrict password field update based on same item or canManagePeople
- [x] Restrict tasks based on same item or canManageTodos
*/
access: {
operation: {
...allOperations(isSignedIn),
create: permissions.canManagePeople,
delete: permissions.canManagePeople,
},
filter: {
query: rules.canReadPeople,
update: rules.canUpdatePeople,
},
},
ui: {
hideCreate: args => !permissions.canManagePeople(args),
hideDelete: args => !permissions.canManagePeople(args),
listView: {
initialColumns: ['name', 'role', 'tasks'],
},
itemView: {
defaultFieldMode: ({ session, item }) => {
// People with canEditOtherPeople can always edit people
if (session.data.role?.canEditOtherPeople) return 'edit';
// People can also always edit themselves
else if (session.itemId === item.id) return 'edit';
// Otherwise, default all fields to read mode
return 'read';
},
},
},
fields: {
/* The name of the user */
name: text({ validation: { isRequired: true } }),
/* The email of the user, used to sign in */
email: text({ isIndexed: 'unique', validation: { isRequired: true } }),
/* The password of the user */
password: password({
validation: { isRequired: true },
access: {
update: ({ session, item }) =>
permissions.canManagePeople({ session }) || session.itemId === item.id,
},
}),
/* The role assigned to the user */
role: relationship({
ref: 'Role.assignedTo',
access: {
create: permissions.canManagePeople,
update: permissions.canManagePeople,
},
ui: {
itemView: {
fieldMode: args => (permissions.canManagePeople(args) ? 'edit' : 'read'),
},
},
}),
/* Todo items assigned to the user */
tasks: relationship({
ref: 'Todo.assignedTo',
many: true,
access: {
// Only people with canManageAllTodos can set this field when creating other users
create: permissions.canManageAllTodos,
// You can only update this field with canManageAllTodos, or for yourself
update: ({ session, item }) =>
permissions.canManageAllTodos({ session }) || session.itemId === item.id,
},
ui: {
createView: {
// Note you can only see the create view if you can manage people, so we just need to
// check the canManageAllTodos permission here
fieldMode: args => (permissions.canManageAllTodos(args) ? 'edit' : 'hidden'),
},
// Todo lists can be potentially quite large, so it's impractical to edit this field in
// the item view. Always set it to read mode.
itemView: { fieldMode: 'read' },
},
}),
},
}),
Role: list({
/*
SPEC
- [x] Block all public access
- [x] Restrict edit access based on canManageRoles
- [ ] Prevent users from deleting their own role
- [ ] Add a pre-save hook that ensures some permissions are selected when others are:
- [ ] when canEditOtherPeople is true, canSeeOtherPeople must be true
- [ ] when canManagePeople is true, canEditOtherPeople and canSeeOtherPeople must be true
- [ ] Extend the Admin UI with client-side validation based on the same set of rules
*/
access: {
operation: {
...allOperations(permissions.canManageRoles),
query: isSignedIn,
},
},
ui: {
hideCreate: args => !permissions.canManageRoles(args),
hideDelete: args => !permissions.canManageRoles(args),
listView: {
initialColumns: ['name', 'assignedTo'],
},
itemView: {
defaultFieldMode: args => (permissions.canManageRoles(args) ? 'edit' : 'read'),
},
},
fields: {
/* The name of the role */
name: text({ validation: { isRequired: true } }),
/* Create Todos means:
- create todos (can only assign them to others with canManageAllTodos) */
canCreateTodos: checkbox({ defaultValue: false }),
/* Manage All Todos means:
- create new Todo items and assign them to someone else (with canCreateTodos)
- update and delete Todo items not assigned to the current user */
canManageAllTodos: checkbox({ defaultValue: false }),
/* See Other Users means:
- list all users in the database (users can always see themselves) */
canSeeOtherPeople: checkbox({ defaultValue: false }),
/* Edit Other Users means:
- edit other users in the database (users can always edit their own item) */
canEditOtherPeople: checkbox({ defaultValue: false }),
/* Manage Users means:
- change passwords (users can always change their own password)
- assign roles to themselves and other users */
canManagePeople: checkbox({ defaultValue: false }),
/* Manage Roles means:
- create, edit, and delete roles */
canManageRoles: checkbox({ defaultValue: false }),
/* This list of People assigned to this role */
assignedTo: relationship({
ref: 'Person.role',
many: true,
ui: {
itemView: { fieldMode: 'read' },
},
}),
},
}),
};