graphql-nexus / nexus-plugin-prisma

Deprecated
MIT License
828 stars 118 forks source link

Prisma2 - disable create/connect on certain inputtypes #518

Open maartenraes opened 4 years ago

maartenraes commented 4 years ago

Problem: We have a nested object structure with objects relying on the existance of other objects. Example: Domain 1 has X organisations with each organisations having it's own X departments and each department having X locations with X classrooms.

When creating a department we want to connect it to an existing organisation but we can't allow upstream creating based on authorization. (An organisation admin can create a new department and link it but not make a new organisation).

The problem we're facing is that all autogenerated InputTypes allow a couple of different ways of creating nested objects (even allowing for empty objects while the relation is required which gives errors when fetching the newly created object; I can provide more info if interested)

It would be usefull that we could provide extra arguments in the typedefinitions that allow us to disable creation of fields but this does not seem possible at the moment.

I've been reading up on some other issues and found this one https://github.com/prisma-labs/nexus-prisma/issues/95. But this seems to use Prisma1 syntax.

Last resort we could do manual but we have 28 models at the moment so I don't really want to go through and overwrite all the different input possibilities manual :-)

schema.prisma:

model Domain  {
  id            String   @default(cuid()) @id
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt

  name          String   @unique
  description   String?
  logo          String?   
  email         String
  telephone     String
  mobilePhone   String
  website       String?

  address       Address
  organisations Organisation[]
  contact       Member
}

model Organisation  {
  id            String   @default(cuid()) @id
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt

  name          String   @unique
  description   String?
  logo          String?   
  email         String
  telephone     String
  mobilePhone   String
  website       String?

  domain        Domain
  address       Address
  departments   Department[]
  contact       Member
}

model Department  {
  id            String   @default(cuid()) @id
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt

  name          String   @unique
  description   String?
  logo          String?   
  email         String
  telephone     String
  mobilePhone   String
  website       String?

  organisation  Organisation
  address       Address
  locations     Location[]
  contact       Member
}

model Location  {
  id            String   @default(cuid()) @id
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt

  name          String   @unique
  description   String?
  walkIn        Boolean   
  email         String
  telephone     String
  mobilePhone   String
  website       String?

  department    Department
  address       Address
  contact       Member
  classrooms    ClassRoom[]
  accessories   Accessory[]
}

model ClassRoom {
  id            String   @default(cuid()) @id
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
}
Weakky commented 4 years ago

Hey @maartenraes,

Thanks for raising that issue. We're planning to add such a feature in the future, it's not planned right now though, and we, unfortunately, have no workaround meanwhile.

Related to: https://github.com/prisma-labs/nexus-prisma/issues/110

maartenraes commented 4 years ago

I'm working on a workaround by using a combination of graphql-shield and Yup validation to validate and disable some nested properties, will update when I get something working 👍

jhalborg commented 4 years ago

If you have specific auth checks for write operations, would it perhaps instead make sense to not expose those through Nexus Prisma and write specific mutations for those operations instead, and then use GraphQL Shield to validate permission for those?

maartenraes commented 4 years ago

It does not fix the entire problem, yes indeed we could write specific mutation, but that would be 96 mutations that we would need to overwrite. That seems a lot of boilerplate for code that's already there, so I would rather find a solution to validate input instead of overwriting all mutations.

Another problem is that you can create objects with an empty object as relation while the relation is required, so even with the graphql shield authorization we would need to validate it anyway with yup.

jasonkuhrt commented 4 years ago

Hey @maartenraes, your input on #598 would be welcome if you have time.

izziaraffaele commented 3 years ago

My 2 cents... You can override nexus generated input types excluding things you don't need...

In your example the input generated from nexus for the field Department.organization should be called OrganizationCreateOneWithoutDepartmentsInput. You can create an input type with the same name where you include only the connect field:

const OrganizationCreateOneWithoutDepartmentsInput = schema.inputObjectType({
  name: 'OrganizationCreateOneWithoutDepartmentsInput',
  definition(t) {
    t.field('connect', { type: 'OrganizationWhereUniqueInput' });
  },
});

This way you just have to rewrite few input types instead of rewriting the entire generated nexus mutation