dimatill / graphql-shield Goto Github PK
View Code? Open in Web Editor NEW🛡 A GraphQL tool to ease the creation of permission layer.
Home Page: https://graphql-shield.com
License: MIT License
🛡 A GraphQL tool to ease the creation of permission layer.
Home Page: https://graphql-shield.com
License: MIT License
Hi! I have tested permissions applied to type which is returned from query and it seems not to work when resolvers for type were not explicitly defined:
for e.g. this works when I do query me:
const resolvers = {
Query: {
me: (_, args, ctx) => ctx.user;
},
User: {
name(parent, args, ctx) { return parent.name; }
}
}
const permissions = shield({
User: {
name: allow
}
})
and this doesn't, although it has allow rule:
const resolvers = {
Query: {
me: (_, args, ctx) => ctx.user;
}
}
const permissions = shield({
User: {
name: allow
}
})
Always getting Not Authorised! error.
Hello, first of all thanks for the great lib!
I have a a question. In docs there is a rule defined and used as:
const isOwner = rule()(async (parent, args, ctx, info) => {
return ctx.user.items.some(id => id === parent.id)
})
const permissions = shield({
/* ... */
User: {
secret: isOwner
},
})
The rule uses parent.id
which is ID of user to determine if the user is a owner. From what I've been able to understand by playing with this library, we can't really rely on any field of parent
.
Let's say the client queries something like:
query {
me {
id
secret
}
}
Where me
is a Query
which returns current user - then everything is correct. However, what if client queries a Query
:
query {
me {
# notice the missing ID
secret
}
}
then the parent.id
in isOwner
rule is undefined and we can't correctly decide whether the user is owner or not.
How can the isOwner
rule be implemented correctly? Is there even a way to do that?
Thanks!
I upgraded v.1.20 to 1.2.6 and my compiler getting error graphql-sheild not found!
Hi,
I fail to understand what is the use of your project. Is it some kind of firewall?
Could you give an example of what it protects from?
Thanks.
In https://github.com/maticzav/graphql-shield/tree/master/examples/with-graphql-middleware-forward-binding example i think any user can connect him posts to another.
I use graphql-middleware-forward-binding
to forward request to db. And i trying to minificate wrapping of generated prisma resolvers by using forwarding and some rules.
So my question is - what the best case of using this package if i want to prevent node reconnecting to other users if i forward request to prisma? I understand what i can just wrap it to another resolvers and prevent owner field to modify, but how can it be done using this package?
For example i have that datamodel.graphql
:
type User implements Node {
id: ID! @unique
competitions: [Competition!]! @relation(name: "UserCompetition")
}
type Competition implements Node {
id: ID! @unique
owner: User! @relation(name: "UserCompetition")
}
Now i forward updateCompetition:
import { forward } from 'graphql-middleware-forward-binding'
export const forwardMiddleware = forward(
'Mutation.updateCompetition',
)('db')
And want to prevent reconnecting user competition to another user by modify owner field:
import { shield } from 'graphql-shield'
import * as rules from './rules'
export const permissions = shield(
{
Mutation: {
updateCompetition: rules.denyChangeOwner,
},
},
)
When I have a query which returns a list, if the first response is good, it's the same for all object in the list, ex:
type Query {
users: [User!]!
}
rules:
shield(
{
User: {
email: isOwner
}
}
)
The rule is just for logic to check if the user authenticated is the same as the requested to allow the request to return the field.
I notice if I add a parameter to the query to change the order, the query is directly denied.
code like this:
const isAuthenticated = rule()(async (parent, args, ctx, info) => {
console.log("call isAuthenticated args = ", args)
return true
})
const permissions = shield({
Query: {
feed: isAuthenticated,
post: isAuthenticated,
},
})
If the query
like this, the isAuthenticated
only be called once !!!
query{
feed{
id
text
}
post(id:"cjk9uyalu00110803ow0wrxwm"){
id
title
}
}
First of all thanks for this amazing library. Thanks a lot. The docs for authorization in Apollo docs suck
I have a doubt, is it possible to authorize subscriptions using graphql-shield
? Mutations are also possible, right?
Hi,
Does anyone know if there is a way to override the standard behaviour of throwing the PermissionError or at least some point to intercept it ?
I am using Log4js to do my logging so I would prefer to intercept these errors.
Anyone have any ideas ?
Hey, I absolutely love this. Thank you so much for your hard work on graphql-shield. One thing that I feel would be super useful is a whitelisting in place of blacklisting feature. Locking everything down and then explicitly exposing access would go a long way to help people develop better habits, be more involved with this part of the process and I think create all around more secure systems.
Thanks for maintaining a great project :)
I'm hoping to use graphql-shield
to lock down my API. Currently I'm using https://github.com/maticzav/graphql-middleware-forward-binding to forward requests to the auto-generated resolvers.
Based on your post (https://medium.com/@maticzav/graphql-shield-9d1e02520e35), does the isCustomer
function ensure that customers can only add items to their own basket? Or how would you add that logic to the function?
When calling addItemToBasket
, are the args
of that mutation passed along to isCustomer
?
I'm using a JWT in the auth header, with a unique ID in the payload. Does that come through in the ctx
variable in some way?
Thanks!
Hi @maticzav! First of all thanks for the awesome library!
I have few questions/suggestions about CustomErrors:
Example:
I have isAuthenticated rule
export default rule()((parent, args, { user }) => Boolean(user));
I want to return my custom 401 error like this
import { SevenBoom } from 'graphql-apollo-errors';
rule(null, {
customError: SevenBoom.unauthorized('You are not authenticated')
})((parent, args, { user }) => Boolean(user))
Example:
import { SevenBoom } from 'graphql-apollo-errors';
shield({ /* Rules… */ }, {
customError: SevenBoom.forbidden('You are not allowed to do this action.')
})
I can implement this and looks like it is not a breaking change.
Just want to clarify if there is no way to do this in current version of the library?
Let me know if you have any questions. Thanks!
First of all, just wanted to add that I love the simplicity of this module, it's certainly made setting up auth in my latest graphql project simpler. Quick question:
I noticed that any errors raised in within my resolvers result in a PermissionError -- is this the intended behavior?
I'm not currently doing anything to handle the errors, so perhaps I should be doing something to deal with them more gracefully; but regardless, I was expecting to receive/log/crash with the original error.
It would be cool if we can customize error message thrown by shield.
Per #57, it would be great to have some docs aroundgraphql-shield
working with graphql-middleware-forward-binding
.
Hi @maticzav,
When I use CustomError of 'graphql-shield" I see it throw message error not clearly, I want to use with apollo-errors.
This link package: https://github.com/thebigredgeek/apollo-errors
Please help me use it!
Thanks for the support!
It seems permissions are only cached when the father ran the same permission function before.
If i want to simply hide a set of fields, for unauthorized users, caching for siblings would come in handy.
like this:
export const userProfilePermissions = {
// isOwnProfile is run 3 x currently
email: isOwnProfile,
phone: isOwnProfile,
address: isOwnProfile
}
Hello!
is graph-shield possible to use with apollo-server-lambda?
I tried to found examples on google how to implement with apollo-server-lambda, but no luck :(
is it possible?
class PermissionError extends Error {
constructor() {
super(`Insufficient permission: ${path}`)
}
}
Is it possible to modify the error
object?
{
"data": null,
"errors": [
{
"message": "Insufficient Permissions.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"getSurveys"
]
}
]
}
Or can we directly use other error handler like apollo-errors instead of using the default "Insufficient permission"
Thanks for the assist!
I just updated to graphql-shield v2.0.6 and now I get this error on running my Node.js app:
RangeError: Maximum call stack size exceeded
at convertRulesToMiddleware (/path-to-server/server/node_modules/graphql-shield/dist/index.js:1:1)
at leafs.reduce (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:84)
at Array.reduce (<anonymous>)
at convertRulesToMiddleware (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:30)
at leafs.reduce (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:84)
at Array.reduce (<anonymous>)
at convertRulesToMiddleware (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:30)
at leafs.reduce (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:84)
at Array.reduce (<anonymous>)
at convertRulesToMiddleware (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:30)
at leafs.reduce (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:84)
at Array.reduce (<anonymous>)
at convertRulesToMiddleware (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:30)
at leafs.reduce (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:84)
at Array.reduce (<anonymous>)
at convertRulesToMiddleware (/path-to-server/server/node_modules/graphql-shield/dist/index.js:232:30)
For authentication purposes, it's a pain to add a rule on every schema entity.
What about a default rule parameter?
My Node.js app runs perfectly fine in development mode.
On running the app in production (by setting NODE_ENV
to production
or using npm install --production
), it throws the following error:
Error: Cannot find module 'chalk'
at Function.Module._resolveFilename (module.js:547:15)
at Function.Module._load (module.js:474:25)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/home/example/app/node_modules/graphql-shield/dist/src/index.js:56:15)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/home/example/app/src/graphql/index.js:1:82)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
If I do just npm install
on my production server without the --production
flag, all works well but I suppose that's not a solution since I don't want to take up space installing devDependencies
on my production server.
ref: dimatill/graphql-middleware#8 (comment)
hi all, i use express + passport-oauth2 in my web.
and i want to use graphql to wrap exist restapi, with permission check.i follow the examples/permissions , but in this line
the
context.request.isAuthenticated()
alway false,
and i debug into the code, it looks like thethis
have nothing about auth info.anybody can tell me how to use this library whit passport ?
I use with-graphql-middleware-forward-binding example.
Order of middlewares not working for me. Shield just not triggered:
const server = new GraphQLServer({
typeDefs: './src/schema.graphql',
resolvers,
resolverValidationOptions: {
requireResolversForResolveType: false
},
middlewares: [permissions, forwardMiddleware],
context: req => ({
...req,
db: new Prisma({
endpoint: process.env.PRISMA_ENDPOINT,
debug: false
})
})
})
My shield:
export const permissions = shield(
{
Mutation: {
updateUser: rules.isSelf,
},
}
)
Forwards:
export const forwardMiddleware = forward(
'Mutation.updateUser',
)('db')
Also i have something my own resolvers:
import { Query } from './Query'
import { auth } from './Mutation/auth'
export default {
Query,
Mutation: {
...auth
}
}
So i change
middlewares: [permissions, forwardMiddleware],
to
middlewares: [forwardMiddleware, permissions],
And shield start catching queries. Maybe i don't understand something and this is expected behavior?
Thank you for this helpful tool!
I am just curious are we allowed by shield principle to update the "context" object from the permissions layer then passing it to the resolvers?
How does do cache work?
How long is the cache life cycle?
Does it create a cache for each request?
Sorry for so many question... Great project!!
is there a restriction on naming permissions that should be documented? https://github.com/maticzav/graphql-shield/blob/0a9c4726d7675db801f87bd5da6a5ff85ac9be69/src/index.ts#L133
I am confused. In examples, there is a fully-hydrated User object. But how we can async fetch it from DB?
Hi everyone,
I'm doing a project that uses graphql but I use graphql with express-graphql. But I want to apply graphql-shield to my project.
Please help me!
Thanks for the support!
import { GraphQLSchema, GraphQLObjectType, } from 'graphql';
import { user, users, usersByRole } from './queries/UserQueries';
const queryType = new GraphQLObjectType({ name: 'QueryType', description: 'The root for all queries available.', fields: { users, user, usersByRole, } });
// Creating schema
const schema = new GraphQLSchema({ query: queryType, });
export const permission = shield({ Query: queryType, });
export default schema;
follow the README, we have to defined the big permission object like this:
const permissions = shield({
Query: {
frontPage: not(isAuthenticated),
fruits: and(isAuthenticated, or(isAdmin, isEditor)),
customers: and(isAuthenticated, isAdmin)
},
Mutation: {
addFruitToBasket: isAuthenticated,
},
Fruit: isAuthenticated,
Cusomer: isAdmin
})
could you give something like merge
const permissions = mergeShield({
1Resolve,
2Resolve,
...
});
master
branch failed. 🚨I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.
You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this 💪.
Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.
Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master
branch. You can also manually restart the failed CI job that runs semantic-release.
If you are not sure how to resolve this, here is some links that can help you:
If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.
The npm token configured in the NPM_TOKEN
environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/
.
If you are using Two-Factor Authentication, make configure the auth-only
level is supported. semantic-release cannot publish with the default auth-and-writes
level.
Please make sure to set the NPM_TOKEN
environment variable in your CI with the exact value of the npm token.
Good luck with your project ✨
Your semantic-release bot 📦🚀
Although I'm an avid user of GraphQL Shield - thank you for creating such a simple means of implementing permissions! - something that has always irked me is that when you implement permissions on a by-type basis, you effectively lose the relational power of GraphQL. Perhaps I'm wrong on this, but this is the issue I see, illustrated with an example:
{
user (input: UserWhereUniqueInput) {
name
age
}
}
Developer sets a basic isAuthenticated
permission on the query to ensure that only logged in users can run this query, but adds no permissions beyond that
A malicious user pokes around the publicly available schema, and finds out that the website stores payment information as CreditCard
nodes that have one-to-one relations with User
nodes
Malicious user simply edits the query to the following, and can now steal people's credit cards:
{
user (input: UserWhereUniqueInput) {
name
age
creditCard {
number
securityCode
}
}
}
I see two solutions to this:
info
of the query to return a pre-determined resultinfo
, compares it to one of several templates based on the user's permissions level, and either throws an error or lets the query throughSince the first solution effectively turns GraphQL into a regular REST endpoint, thereby defeating the purpose, I ended up rolling my own solution that implements #2 using graphql-fields
. It even allows for functions to be passed in that can evaluate the input at runtime, and determine whether to authorize the operation or not based on the actual query input. Here's an example with a mutation:
export default {
Mutation: {
createCollectionAsPartner: rule()(
async (parent, { collectionCreateInput }, ctx: Context, info) => {
const permissionFunction: PermissionFunction = (): boolean => {
return collectionCreateInput.collectionVersions.create.deleted !== false;
};
const permissionDefinition: PermissionDefinition = {
collectionVersions: {
create: {
name: true,
deleted: permissionFunction,
externalFiles: {
create: {
applicationType: true,
},
},
},
},
};
const verified = verifyMutationPermissions(
collectionCreateInput,
permissionDefinition,
'createCollectionAsPartner'
);
return verified;
}
),
},
};
Using this definition, this mutation would work, because name
is defined as true
in the PermissionDefinition
object:
mutation {
createCollectionAsPartner(collectionCreateInput: {collectionVersions: {create: { name: "12345"}}})
}
While this one would not, because approvedManually
is not defined in the PermissionDefinition
object:
mutation {
createCollectionAsPartner(collectionCreateInput: {collectionVersions: {create: { approvedManually:true}}})
}
This example is based on typings generated by Prisma, and limits what kind of input can be passed in when creating this type to the ones defined and equal to true
in the PermissionDefinition object. If a field is not defined in the object, or is defined but as either false
or a sync/async function that resolves to false
at runtime, the operation is denied. The end result is extremely granular control over what is and isn't allowed, without sacrificing the ability to query/mutate by relations, the greatest strength in GraphQL.
Although I wouldn't necessarily expect this to make it into the native library, I'd love to hear everyone's thoughts on this approach! I was surprised to see how little attention this critical security issue is getting within the GraphQL community, but it's possible that I'm just doing something totally wrong and this isn't a problem with a correct setup.
Add support for fragments
in rules, so we can rely on nested data.
const nestedRule = rule({
cache: 'strict',
fragment: 'fragment UserID on User { id }',
})(async ({ id }, args, ctx, info) => {
return somethingWithID(id)
})
Hi,
I sort of missed the update and just noticed it now.
I just wanted to say that everything seems to be working as planned! Great update and thanks for your time and effort.
Your implementation of passing {debug: true} works great for me to allow graphql-errors to pick up the error message that I originally threw inside my resolvers / permissions.
Maybe the property name should be allowExternalErrors or something similar as debug seems to shout something to do with debugging.
But hey, it works!
Thanks once again!
I hope I will have a time for that soon.
https://github.com/maticzav/graphql-shield/blob/master/src/types.ts
A bit of context, shield
is meant to be a wrapper for resolvers. Currently, the two parameters it accepts are permissions
and resolvers
- I think that adding typeDefs
as another argument makes everything unnecessarily more complex.
The problem is that since people often only define types in typeDefs
but do not resolve them in resolvers (graphql
manages this for them automatically behind the scenes). When generating resolvers from permissions
, I cannot tell which resolvers might exist in the end since I can obtain only the keys in defined resolvers
and permissions
.
Let’s say, for example, that we have such schema and permissions…
type Query {
text: String!
list: [String!]!
type: Type!
}
type Mutation {
development: String!
}
type Type {
property: String!
properties: [String!]!
hiddenProperty: String!
}
schema {
query: Query,
mutation: Mutation
}
const _permissions = {
Query: () => true,
Type: {
property: () => true,
properties: () => true
// hiddenProperty should by default be blacklisted
}
}
Now we have two options for resolving Type
; first, resolving it only in Query and second, resolving it under Type
. Taking the first approach the exact scenario occurs, since neither resolvers
nor permissions
define hiddenProperty
key, shield
cannot make a tree this deep and hiddenProperty
query is always resolved.
const _resolvers = {
Query: {
text: () => 'simpletext',
list: () => ['firsttext', 'secondtext', 'thirdtext'],
type: () => ({
property: 'typeproperty',
properties: [
'firsttypeproperty',
'secondtypeproperty',
'thirdtypeproperty'
],
hiddenProperty: 'hiddentypeproperty'
})
},
Mutation: {
development: () => 'notpublic'
},
}
On the other hand, the following works as expected.
const _resolvers = {
Query: {
text: () => 'simpletext',
list: () => ['firsttext', 'secondtext', 'thirdtext'],
type: () => ({})
},
Mutation: {
development: () => 'notpublic'
},
Type: {
property: () => 'typeproperty',
properties: () => [
'firsttypeproperty',
'secondtypeproperty',
'thirdtypeproperty'
],
hiddenProperty: () => 'hiddentypeproperty'
}
}
First of all I think that graphql-shield add a clean, generic and maintainable security layer to graphql.
It don't replace ad-hoc fine-grained security check in some resolver for special cases but make easy to add uniform basic access control on all your schema.
So kudos to you!
I'm implementing a field level access policies with graphql-shield but I'm having a strange issue.
When a field is "Not Authorised!" the parent object is set to null.
Here is an example.
Permissions:
const permissions = shield({ Query: { node: allow, }, User: { name: allow, secret: deny } });
Query:
{ node (id: 'myId') { ... on User { name, secret } } }
Expected result:
{ "data": { "node": { name: "My name" } }, "errors": [ { "message": "Not Authorised!", "locations": [ { "line": 31, "column": 3 } ], "path": [ "node", "secret" ] } ] }
Actual result:
{ "data": { "node": null }, "errors": [ { "message": "Not Authorised!", "locations": [ { "line": 31, "column": 3 } ], "path": [ "node", "secret" ] } ] }
It's not an errorPolicy issue on the client because this is extracted from the raw http response.
Only parent object is set to null.
A connection query has all fields normally returned but edges are like this
edges { edge { node: null }, edge { node: null }, edge { node: null }, edge { node: null } }
I'd like to adopt graphql-shield so let me know if I can help to solve this issue.
Thanks.
graphql-shield
headedFirst, thanks for all the great feedback you've all given me so far. While listening to you and thinking about what I want and how I would like to use graphql-shield
in my projects, I came to some conclusions, which will lead the second version of this package.
The most requested feature and I, in my opinion, the most important one is whitelisting
. Whitelisting, in comparison to blacklisting, requires all the exposed queries to be explicitly allowed in order to be used. Adoption of whitelisting also brings a lot easier stage separation as queries/mutations can be allowed in the development phase and restricted in production.
interface Options {
debug: true // -> makes all the queries "available"
cache: true
}
Currently, graphql-shield
only supports nesting permissions using type-specific permissions, which get evaluated during execution chain.
const permissions = {
Query: {
me: authenticated
},
Me: {
id: isMe,
name: isMe,
secret: isMe
}
}
I think that the best approach to tackle this problem is by making possible lists
of permissions.
const permissions = {
Query: {
me: [authenticated, isMe]
},
}
As things get more complicated you might as well want to make some permissions optional (OR
), which would require helper functions like oneOf
and all
to make it all possible.
const permissions = {
Query: {
posts: oneOf(isAdmin, isEditor, isOwner),
oneTimeLatter: all(isAuthenticated, latterNotRead)
}
}
This is also the solution I am aiming for.
Right now, you can only restrict certain fields and the entire types
altogether. By introducing whitelisting
instead of blacklisting
this feature becomes essential as having to explicitly allow each field for each type is all too much work. In my opinion, making Type
general permissions available would perfectly solve this problem.
const permissions = {
Query: {
me: auth
},
Me: allowAllFields
}
I think that most of the functionality should be directed to developers during the development stage. By introducing the right tools to make permission handling as easy as possible, we can make an actual difference with graphql-shield
.
Few ideas:
I'm wondering if it's possible to return different result for different users.
for example, i want to only permit users to see the posts they've created themselves. Should this be managed and can this be managed by graphql-shield?
Many thanks.
This looks really awesome, especially with the new features coming in 3.0!
I'm currently using schema directives to enforce permissions based on Apollo's docs. I've added two features that really benefit my app:
So, I have a couple questions. I'm also happy to contribute to any of these features if they seem possible and interesting.
isAuthenticated
and isAdmin
etc. could be derived.We do caching regardless of if the rule uses field specific data like parent
, args
or info
Apollo Server 2.0 added the ability to add error codes. Out of the box there are three error code types:
I propose that graphql-shield should throw ForbiddenError
. This results in a more meaningful, standardised response on the client.
from:
extensions: { code :"INTERNAL_SERVER_ERROR" },
message: "Not Authorised!"
to:
extensions: { code :"FORBIDDEN" },
message: "Not Authorised!"
ForbiddenError can be imported from apollo-server:
import { ForbiddenError } from 'apollo-server'
I have a current workaround by setting allowExternalErrors
to true and throwing this error from the rule resolver.
export interface IResolverOptions {
resolve?: IFieldResolver<any, any>;
subscribe?: IFieldResolver<any, any>;
__resolveType?: GraphQLTypeResolver<any, any>;
__isTypeOf?: GraphQLIsTypeOfFn<any, any>;
}
I'm following the examples for setting up with Prisma (using the Prisma graphql-authentication
example) and everything is working great except when I try to use parent
in a rule to establish user ownership.
const isOwner = rule()(async (parent, args, ctx, info) => {
// Here, ctx contains my proper user object but parent is always undefined
// without this permission, the yoga resolves the mutation just fine and the updated post is returned
return ctx.user.items.some(id => id === parent.id)
})
const permissions = shield({
Mutation: {
updatePost: or(isAdmin, and(isOwner, isEditor))
},
})
What I see is that the isOwner
rule is being called before my updatePost
resolver. Is this the intended behavior? Kinda makes sense not to hit the database if not authorized but then I have no chance to check the ownership of the post
.
Does anyone know how parent
is supposed to be populated? @maticzav explains nicely in dimatill/graphql-middleware#19 that parent
is the "result of the previous function. GraphQL works recursively by calling successive types determined by the schema. It starts off with undefined and continues execution down the chain forwarding the result of the previous resolver to the new one." Ok. But my resolver is never called. What am I doing wrong?
Thanks so much!!
A use case I'm interested in is putting permissions on input types and individual fields of input types. This would simplify mutation permissions because you could use a generic mutation like updateUser
but limit access to modifying certain fields of User
.
Is this supported or possible to add? I'd be happy to contribute if interested.
Let's assume I have Users and Posts, and want to create a UpdatePost mutation and also want to make sure, that only the creator of the post can edit it. I could take the userid from the context (which comes from token auth) and match it with the authorId. But is there a more elegant way to do this via a middleware with graphql-shield?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.