Nexus-plugin-prisma: Possibility to only retreive owners data

Created on 22 Feb 2020  路  3Comments  路  Source: graphql-nexus/nexus-plugin-prisma

When specifing computedInput for the default data that should be set for certain fields in models. The option to retreive the data by one of these fields dissapears.

plugins: [nexusPrismaPlugin(
    {
      computedInputs: {
        user: ({ ctx }) => ({ connect: { id: ctx.userId } }),
        company: ({ ctx }) => ({ connect: { id: ctx.companyId } }),
        // Need to get the addresses where the user.id === ctx.userId
      }
    }
  )],

with this config, my user and company fields dissapears from queries to fetch multiple objects ex;

image

So at this moment it is impossible to retreive the data that owned by the user that makes the request. (Rather then retrieving all the data and filter it in the client (frontend))

Ideally i would like to use it by setting a default filter the same way computedInputs are declared

ex;

plugins: [nexusPrismaPlugin(
    {
      computedInputs: {
      ...
      },
      computedFilters: {
        addresses: ({ ctx }) => ({ where: { user: { id: ctx.userId } } }),
        relations: ({ ctx }) => ({ where: { user: { id: ctx.userId } } }),
        ...
      }
    }
  )],

So this would only return the addresses and / or projects where the user.id is equal to ctx.userId when querying.

If there is a other way to get the same result, please let me know, i'm really stuck with this issue.

Most helpful comment

It is a important feature

All 3 comments

I have the same problem, I like the t.crud / t.model solution but it lacks a solution to add a custom filter

For my example I wish that the t.crud requests be filtered according to a user

model User {
    id               Int     @id @default(autoincrement())
    email            String  @unique
    password         String
    name             String?
    products         product[]
}

model Product {
    id                 Int     @id @default(autoincrement())
    user               User ?
    key                String  @unique
}

/* 
this line is necessary to generate ProductWhereInput
I have to add permission to deny access
*/
t.crud.products( { alias:"allProducts", filtering : true, ordering : true} )
////////////

t.list.field('products', {
    type: 'Product',
    args: {
        where : arg({ type: 'ProductWhereInput' }),
        orderBy : arg({type: 'ProductOrderByInput'}),
        skip: intArg(),
        after: intArg(),
        before: intArg(),
        first: intArg(),
        last: intArg(),
    },
    resolve: async (parent, args, ctx) => {
        const userId  = getUserId(ctx)
        return ctx.prisma.product.findMany({
            where: {
                AND : [
                    args.where || {},
                    { user : { id :  userId } } // my custom filter
                ]
            },
            orderBy : args.orderBy,
            skip : args.skip,
            after : args.after,
            before : args.before,
            first : args.first,
            last : args.last,
        })
    }
})

my ideal solution

t.crud.products({
    filtering : true, 
    ordering : true
    customFilter : function(parent, args, ctx) {
        return { user : { id :  getUserId(ctx) } }
    }
})

more it would be interesting to have a solution to generate args from prisma models

for exemple :

t.list.field('products', {
        type: 'Product',
        args: t.args.ProductBashRead( { alias:"myalias", filtering : true, ordering : true } ),
})

It is a important feature

I use nexus-prisma together with the graphql-yoga and the latter allows you to define custom middleware. In such middleware you can filter user args and push them to the underlying resolver. This is how the server setup is to allow filtering use provided where argument and further limit it with extra parameters

import { GraphQLServer } from 'graphql-yoga';
import { schema } from './schema';
import { createContext } from './schema/context';

const argsFilter = {
    Query: {
        users: async (resolve, parent, args, ctx, info) => {
            // ctx.prisma is available here and gives access
            // to existing prisma instance

            // const usersCount = await ctx.prisma.user.count();

            const newArgs = {
                where: {
                    AND: [
                        args.where || {},   // Get original 'where' from user args or use empty one
                        { id: 3 }           // Add our own extra limitation
                    ]
                }
            };

            // pass new args to the underlying resolver where it will be handled 
            // by nexus-prisma and its default crud
            return resolve(parent, newArgs, ctx, info);
        }
    }
}

const server = new GraphQLServer({
    schema,
    context: createContext,
    middlewares: [argsFilter],
});

server.start((options) =>
    console.log(`Server ready at: http://localhost:${options.port}`),
);
Was this page helpful?
0 / 5 - 0 ratings