diff --git a/modules/core/graph/directives/isAuthorizedForBranch.js b/modules/core/graph/directives/isAuthorizedForBranch.js new file mode 100644 index 000000000..234d0f3bd --- /dev/null +++ b/modules/core/graph/directives/isAuthorizedForBranch.js @@ -0,0 +1,29 @@ +const { ApolloError, ForbiddenError, SchemaDirectiveVisitor } = require( 'apollo-server-express' ) +const { defaultFieldResolver } = require( 'graphql' ) +const appRoot = require( 'app-root-path' ) +const { authorizeResolver } = require( `${appRoot}/modules/shared` ) + +module.exports = { + isAuthorizedForStream: class IsAuthorizedForStreamDirective extends SchemaDirectiveVisitor { + visitFieldDefinition( field ) { + const { resolver = field.resolve || defaultFieldResolver, name } = field + const requiredRole = this.args.role + let resourceId + + field.resolve = async function ( parent, args, context, info ) { + if ( info.parentType == 'Subscription' ) { + resourceId = ( parent[ name ].streamId || parent[ name ].id ) + } else { + resourceId = args.branch.streamId + } + + if ( !resourceId ) throw new ApolloError( 'Could not find the resource id' ) + + await authorizeResolver( context.userId, resourceId, requiredRole ) + + const data = await resolver.call( this, parent, args, context, info ) + return data + } + } + } +} diff --git a/modules/core/graph/directives/isAuthorizedForCommit.js b/modules/core/graph/directives/isAuthorizedForCommit.js new file mode 100644 index 000000000..396fb24e2 --- /dev/null +++ b/modules/core/graph/directives/isAuthorizedForCommit.js @@ -0,0 +1,29 @@ +const { ApolloError, ForbiddenError, SchemaDirectiveVisitor } = require( 'apollo-server-express' ) +const { defaultFieldResolver } = require( 'graphql' ) +const appRoot = require( 'app-root-path' ) +const { authorizeResolver } = require( `${appRoot}/modules/shared` ) + +module.exports = { + isAuthorizedForStream: class IsAuthorizedForStreamDirective extends SchemaDirectiveVisitor { + visitFieldDefinition( field ) { + const { resolver = field.resolve || defaultFieldResolver, name } = field + const requiredRole = this.args.role + let resourceId + + field.resolve = async function ( parent, args, context, info ) { + if ( info.parentType == 'Subscription' ) { + resourceId = ( parent[ name ].streamId || parent[ name ].id ) + } else { + resourceId = args.commit.streamId + } + + if ( !resourceId ) throw new ApolloError( 'Could not find the resource id' ) + + await authorizeResolver( context.userId, resourceId, requiredRole ) + + const data = await resolver.call( this, parent, args, context, info ) + return data + } + } + } +} diff --git a/modules/core/graph/directives/isAuthorizedForStream.js b/modules/core/graph/directives/isAuthorizedForStream.js new file mode 100644 index 000000000..a44ee8478 --- /dev/null +++ b/modules/core/graph/directives/isAuthorizedForStream.js @@ -0,0 +1,29 @@ +const { ApolloError, ForbiddenError, SchemaDirectiveVisitor } = require( 'apollo-server-express' ) +const { defaultFieldResolver } = require( 'graphql' ) +const appRoot = require( 'app-root-path' ) +const { authorizeResolver } = require( `${appRoot}/modules/shared` ) + +module.exports = { + isAuthorizedForStream: class IsAuthorizedForStreamDirective extends SchemaDirectiveVisitor { + visitFieldDefinition( field ) { + const { resolver = field.resolve || defaultFieldResolver, name } = field + const requiredRole = this.args.role + let resourceId + + field.resolve = async function ( parent, args, context, info ) { + if ( info.parentType == 'Subscription' ) { + resourceId = ( parent[ name ].streamId || parent[ name ].id ) + } else { + resourceId = ( args.id || args.streamId || args.stream.id ) + } + + if ( !resourceId ) throw new ApolloError( 'Could not find the resource id' ) + + await authorizeResolver( context.userId, resourceId, requiredRole ) + + const data = await resolver.call( this, parent, args, context, info ) + return data + } + } + } +}