epicweb-dev/web-auth

I think it's possible to enforce that a password is required on the User model without leaking it.

alejandrorpascual opened this issue ยท 4 comments

In exercise 4 you wrote:

Unfortunately, it's not possible to enforce that a password is required on the User model at the database level. However, it's worth the tradeoff to avoid the risk of leaking passwords.

I was checking the Prisma docs for one-to-one relationships, and found that if you change the relationship scalar (or foreign key) you can make the password field required when creating a User

from Prisma docs (Required and optional 1-1 relation fields)

model User {
  id      Int      @id @default(autoincrement())
  profile Profile? // No relation scalar - must be optional
}

However, you can choose if the side of the relation with a relation scalar should be optional or mandatory. In the following example, profile and profileId are mandatory. This means that you cannot create a User without connecting or creating a Profile:

model User {
  id        Int     @id @default(autoincrement())
  profile   Profile @relation(fields: [profileId], references: [id]) // references `id` of `Profile`
  profileId Int     @unique // relation scalar field (used in the `@relation` attribute above)
}

model Profile {
  id   Int   @id @default(autoincrement())
  user User?
}

so, if you do something like this:

model Password {
  id   String @id @default(cuid())
  hash String
  // ๐Ÿ‘‡ Now this is optional
  user User?
}


model User {
  id       String  @id @default(cuid())
  email    String  @unique
  username String  @unique
  name     String?

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  image      UserImage?
  // ๐Ÿ‘‡ note the fields here.
  password   Password   @relation(fields: [passwordId], references: [id])
  passwordId String     @unique

  notes Note[]
}

The password would be required for User creation, and I think it won't eagerly load the relationship field (password on the User model in this case) because Prisma doesn't load those by default.

Good point! Unfortunately this just moves the problem: now you can't enforce the user is required on the password. This was my intent with what I said. You can't enforce this to be required on both sides of the relationship.

But what you've said could be added as a note in the exercise instructions. Would you be interested in making a contribution? It could even be just a link to this issue.

Thanks for the help!