npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

secure-graphql-object-type

v1.4.4

Published

Simple way to secure graphql fields.

Downloads

18

Readme

secure-graphql-object-type

Simple way to secure graphql fields.

Install

yarn add secure-graphql-object-type npm install secure-graphql-object-type --save

Why ?

In graphQl you can specify that you wanna give access to a field or not using the resolve function. But imagine this field is a graphQlObjectType, maybe you want to give access to some of his fields but not others. Staying with graphQlObjectType you could still code this inside the resolve function of every field inside the graphQlObjectType but it can be limited.

Here is an example :

You have a userType which contain a profileType :

const UserProfileType = new GraphQLObjectType({
  name: 'UserProfile',
  fields () {
    return {
      firstname: {
        type: GraphQLString
      },
      lastname: {
        type: GraphQLString
      },
      age: {
        type: GraphQlInt
      }
    }
  }
})

const UserType = new GraphQLObjectType({
  name: 'User',
  fields () {
    return {
      _id: {
        type: GraphQLID
      },
      profile: {
        type: UserProfileType
      }
    }
  }
})

Now if you want to secure the age depending on the user connected correspond to the user we're returning you're stuck because you can't have access inside UserProfileType to _id inside UserType. It would still be possible passing the _id to the child UserProfileType and check inside the resolve function to make the check but it's really heavy and not handy:

const UserProfileType = new GraphQLObjectType({
  name: 'UserProfile',
  fields () {
    return {
      firstname: {
        type: GraphQLString
      },
      lastname: {
        type: GraphQLString
      },
      age: {
        type: GraphQLInt,
        resolve (parent, args, context) {
          return context.connectedUserId === parent.$_id ? parent.age : null
        }
      }
    }
  }
})

const UserType = new GraphQLObjectType({
  name: 'User',
  fields () {
    return {
      _id: {
        type: GraphQLID
      },
      profile: {
        type: UserProfileType,
        resolve (parent) {
          const _profile = parent.profile

          _profile.$_id = parent._id

          return _profile
        }
      }
    }
  }
})

How ?

Keeping the same problem as above but now using SecureGraphQlObjectType you simply have to do that :

const UserProfileType = new SecureGraphQlObjectType({
  name: 'UserProfile',
  fields () {
    return {
      firstname: {
        type: GraphQLString
      },
      lastname: {
        type: GraphQLString
      },
      age: {
        type: GraphQLInt,
        secure: true
      }
    }
  }
})

const UserType = new SecureGraphQlObjectType({
  name: 'User',
  fields () {
    return {
      _id: {
        type: GraphQLID
      },
      profile: {
        type: UserProfileType,
        secureCheck (parent, args, context) {
          const parentHasAccess = parent.$hasAccess
          const userHasAccess = parent._id === context.userId 

          const hasAccess = parentHasAccess || userHasAccess

          return hasAccess
        }
      }
    }
  }
})

The check will be done in the secureCheck function and apply to every sub fields under UserProfileType even if UserProfileType had another sub field with secure fields it would still apply to those.

You will also see that I use parent.$hasAccess. Every SecureGraphQlObjectType will have access to the parent.$hasAccess property, if it's true it means that the parent check already passed. If you don't precise any secureCheck, it will check by default only parent.$hasAccess if the field is secure, like it does for the age under UserProfile.

Details

fieldsToAvoid :

You can specity an array of fieldsToAvoid in every SecureGraphQlObjectType. By default this array will be equal to ['$hasAccess', '$parent']

Those fields are not part of the object you wanna return but you still want to use them in sub objectTypes.

If we take our previous example imagine that I want to pass a property $test to my sub objectType UserProfileType for no specific reasons here:

const UserProfileType = new SecureGraphQlObjectType({
  name: 'UserProfile',
  fieldsToAvoid: ['$hasAccess', '$parent', '$test'],
  fields () {
    return {
      firstname: {
        type: GraphQLString
      },
      lastname: {
        type: GraphQLString
      },
      age: {
        type: GraphQLInt,
        resolve (parent) {
          // parent.$test === 'My test'

          return parent.age
        },
        secure: true
      }
    }
  }
})

const UserType = new SecureGraphQlObjectType({
  name: 'User',
  fields () {
    return {
      _id: {
        type: GraphQLID
      },
      profile: {
        type: UserProfileType,

        secureCheck (parent, args, context) {
          const parentHasAccess = parent.$hasAccess
          const userHasAccess = parent._id === context.userId 

          const hasAccess = parentHasAccess || userHasAccess

          return hasAccess
        },
        resolve (parent) {
          const _profile = parent.profile

          _profile.$test = 'My test'

          return _profile
        }
      }
    }
  }
})

As you can see here I pass the property $test to my profile and to be able to use it inside UserProfileType I need to specify that $test will be a fieldsToAvoid.

You can find a sample here : Sample