Skip to content

Commit

Permalink
Password field updates (#6683)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmatown authored Sep 30, 2021
1 parent b2349ca commit b769747
Show file tree
Hide file tree
Showing 15 changed files with 372 additions and 177 deletions.
5 changes: 5 additions & 0 deletions .changeset/many-pandas-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-next/keystone': major
---

In the `password` field, `defaultValue` has been removed, `isRequired` has moved to `validation.isRequired`, `rejectCommon` has moved to `validation.rejectCommon`, `minLength` has moved to `validation.length.min` along with with the new `validation.length.max` and `validation.match` options. The `password` field can also be made non-nullable at the database-level with the `isNullable` option which defaults to `true`. Also, providing `''` to the field will now result in an error instead of silently setting null. `validation.length.min` also must be `1` or above, though it still defaults to `8`. If `workFactor` is outside of the range of `6` to `31`, an error will now be thrown instead of the previous behaviour of clamping the value to `4` to `31` and warning if it's below `6`.
23 changes: 17 additions & 6 deletions docs/pages/docs/apis/fields.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -373,9 +373,17 @@ A `password` field represents an encrypted password value.

Options:

- `isRequired` (default: `false`): If `true` then this field can never be set to `null`.
- `minLength` (default: `8`): The minimum length password accepted.
- `rejectCommon` (default: `false`): Rejects passwords from a list of commonly used passwords.
- `isNullable` (default: `false`): If `true` then this field will be made nullable in the database and it will be possible to set as `null`.
- `validation.isRequired` (default: `false`): If `true` then this field can never be set to `null`.
Unlike `isNullable`, this will require that a value is provided in the Admin UI.
It will also validate this when creating and updating an item through the GraphQL API but it will not enforce it at the database level.
If you would like to enforce it being non-null at the database-level and in the Admin UI, you can set both `isNullable: false` and `validation.isRequired: true`.
- `validation.length.min` (default: `8`): This describes the minimum length allowed. If you attempt to submit a string shorter than this, you will get a validation error.
- `validation.length.max` (default: `undefined`): This describes the maximum length allowed. If you attempt to submit a string longer than this, you will get a validation error.
- `validation.match` (default: `undefined`): This describes a pattern that values for this field must match
- `validation.match.regex`: The regular expression
- `validation.match.explanation` (default: `${fieldLabel} must match ${validation.match.regex}`): A message shown in the Admin when a value doesn't match the regex and returned as a validation error from the GraphQL API
- `validation.rejectCommon` (default: `false`): Rejects passwords from a list of commonly used passwords.
- `bcrypt` (default: `require('bcryptjs')`): A module which implements the same interface as the [`bcryptjs`](https://www.npmjs.com/package/bcryptjs) package, such as the native [`bcrypt`](https://www.npmjs.com/package/bcrypt) package.
This module will be used for all encryption routines in the `password` field.

Expand All @@ -388,9 +396,12 @@ export default config({
ListName: list({
fields: {
fieldName: password({
isRequired: true,
minLength: 10,
rejectCommon: true,
isNullable: false,
validation: {
length: { min: 10, max: 1000 },
isRequired: true,
rejectCommon: true,
},
bcrypt: require('bcrypt'),
}),
/* ... */
Expand Down
2 changes: 1 addition & 1 deletion examples-staging/roles/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ model Person {
id String @id @default(cuid())
name String @default("")
email String @unique @default("")
password String?
password String
role Role? @relation("Person_role", fields: [roleId], references: [id])
roleId String? @map("role")
tasks Todo[] @relation("Todo_assignedTo")
Expand Down
3 changes: 2 additions & 1 deletion examples-staging/roles/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ export const lists = {
email: text({ isIndexed: 'unique', isFilterable: true, validation: { isRequired: true } }),
/* The password of the user */
password: password({
isRequired: true,
isNullable: false,
validation: { isRequired: true },
access: {
update: ({ session, item }) =>
permissions.canManagePeople({ session }) || session.itemId === item.id,
Expand Down
5 changes: 0 additions & 5 deletions examples/testing/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,9 @@ input PersonWhereInput {
id: IDFilter
name: StringFilter
email: StringFilter
password: PasswordFilter
tasks: TaskManyRelationFilter
}

input PasswordFilter {
isSet: Boolean!
}

input TaskManyRelationFilter {
every: TaskWhereInput
some: TaskWhereInput
Expand Down
10 changes: 5 additions & 5 deletions examples/testing/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ model Task {
}

model Person {
id String @id @default(cuid())
name String @default("")
email String @unique @default("")
password String?
tasks Task[] @relation("Task_assignedTo")
id String @id @default(cuid())
name String @default("")
email String @unique @default("")
password String
tasks Task[] @relation("Task_assignedTo")
}
2 changes: 1 addition & 1 deletion examples/testing/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const lists = {
fields: {
name: text({ validation: { isRequired: true } }),
email: text({ isIndexed: 'unique', validation: { isRequired: true } }),
password: password({ isRequired: true }),
password: password({ isNullable: false, validation: { isRequired: true } }),
tasks: relationship({ ref: 'Task.assignedTo', many: true }),
},
defaultIsFilterable: true,
Expand Down
2 changes: 1 addition & 1 deletion examples/with-auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ These are used as our _identity_ and _secret_ fields for login.

```typescript
email: text({ isIndexed: 'unique', isFilterable: true, validation: { isRequired: true } }),
password: password({ isRequired: true }),
password: password({ isNullable: false, validation: { isRequired: true } }),
```

### Auth config
Expand Down
5 changes: 0 additions & 5 deletions examples/with-auth/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,9 @@ input PersonWhereInput {
id: IDFilter
name: StringFilter
email: StringFilter
password: PasswordFilter
tasks: TaskManyRelationFilter
}

input PasswordFilter {
isSet: Boolean!
}

input TaskManyRelationFilter {
every: TaskWhereInput
some: TaskWhereInput
Expand Down
10 changes: 5 additions & 5 deletions examples/with-auth/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ model Task {
}

model Person {
id String @id @default(cuid())
name String @default("")
email String @unique @default("")
password String?
tasks Task[] @relation("Task_assignedTo")
id String @id @default(cuid())
name String @default("")
email String @unique @default("")
password String
tasks Task[] @relation("Task_assignedTo")
}
4 changes: 2 additions & 2 deletions examples/with-auth/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export const lists = {
email: text({ isIndexed: 'unique', isFilterable: true, validation: { isRequired: true } }),
// The password field stores a hash of the supplied password, and
// we want to ensure that all people have a password set, so we use
// the isRequired flag.
password: password({ isRequired: true }),
// the validation.isRequired and isNullable: false flags.
password: password({ isNullable: false, validation: { isRequired: true } }),
tasks: relationship({ ref: 'Task.assignedTo', many: true }),
},
defaultIsFilterable: true,
Expand Down
Loading

0 comments on commit b769747

Please sign in to comment.