SoftwareBrothers / adminjs

AdminJS is an admin panel for apps written in node.js
https://adminjs.co
MIT License
8.07k stars 650 forks source link

[Bug]: AdminJs/relations and Prisma Many to Many with undefined references causes `Argument in: Invalid value provided` #1620

Closed ZanderFoster closed 4 months ago

ZanderFoster commented 5 months ago

Contact Details

No response

What happened?

When trying to use many to many with a model that has a optional reference, the entries without a reference cause Prisma to throw a error because it expects nulled or undefined values to be filtered out when calling prisma.[KEY].findMany()

Bug prevalence

When trying to view a list from the relation owner and at least one entry in the junction model contains a null or undefined reference.

AdminJS dependencies version

"dependencies": { "@adminjs/express": "^6.1.0", "@adminjs/logger": "^5.0.1", "@adminjs/passwords": "^4.0.0", "@adminjs/prisma": "^5.0.2", "@adminjs/relations": "^1.0.1", "@adminjs/themes": "^1.0.1", "@adminjs/upload": "^4.0.2", "@prisma/client": "^5.6.0", "adminjs": "^7.4.1", },

What browsers do you see the problem on?

No response

Relevant log output

PrismaClientValidationError: 
Invalid `prisma.user.findMany()` invocation:

{
  where: {
    id: {
      in: [
        null,
        1,
        1
      ]
      ~~~~~~
    }
  }
}

Argument `in`: Invalid value provided. Expected ListIntFieldRefInput, provided (Null, Int, Int).

Relevant code that's giving you issues

model User {
  id          Int                @id @default(autoincrement())
  createdAt   DateTime           @default(now()) @map("created_at")
  updatedAt   DateTime           @updatedAt @map("updated_at")
  lastActive  DateTime?          @map("last_active")
  username    String             @unique
  password    String
  email       String             @unique
  appLicenses AppLicense[]

  @@map("users")
}

model Application {
  id        Int           @id @default(autoincrement())
  createdAt DateTime      @default(now()) @map("created_at")
  updatedAt DateTime      @updatedAt @map("updated_at")
  licenses  AppLicense[]

  @@map("applications")
}

model AppLicense {
  id        Int         @id @default(autoincrement())
  createdAt DateTime    @default(now()) @map("created_at")
  updatedAt DateTime    @updatedAt @map("updated_at")

  appId     Int         @map("app_id")
  app       Application @relation(fields: [appId], references: [id])
  userId    Int?        @map("user_id")
  user      User?       @relation(fields: [userId], references: [id])
  key       String      @default(uuid())

  @@map("app_licenses")
}
owningRelationSettingsFeature({
  componentLoader,
  licenseKey: process.env.ADMINJS_RELATIONS_LICENSEKEY,
  relations: {
      keys: {
          type: RelationType.OneToMany,
          target: {
              joinKey: 'app',
              resourceId: 'AppLicense',
          },
      },

      users: {
          type: RelationType.ManyToMany,
          junction: {
              joinKey: 'app',
              inverseJoinKey: 'user',
              throughResourceId: 'AppLicense',
          },
          target: {
          resourceId: 'User',
          },
      },
},
dziraf commented 5 months ago

@ZanderFoster could you try with @adminjs/relations @ 1.1.1? The ids provided to findMany are now filtered to exclude undefined and null values if such exist in the list.