Exemplo n.º 1
0
        /// <summary>
        /// Configures the services and settings for the schema using the supplied configuration function.
        /// </summary>
        public void ConfigureServices()
        {
            // create the builder to guide the rest of the setup operations
            _options = new SchemaOptions(typeof(TSchema));
            _schemaBuilder.TypeReferenceAdded += this.TypeReferenced_EventHandler;
            _options.TypeReferenceAdded       += this.TypeReferenced_EventHandler;

            _configureOptions?.Invoke(_options);

            // register global directives to the schema
            foreach (var type in Constants.GlobalDirectives)
            {
                _options.AddGraphType(type);
            }

            // add execution assembly for auto loading of graph types
            if (_options.AutoRegisterLocalGraphEntities)
            {
                var assembly = Assembly.GetEntryAssembly();
                _options.AddGraphAssembly(assembly);
            }

            // ensure some http processor is set
            if (_options.QueryHandler.HttpProcessorType == null)
            {
                if (_options.QueryHandler.AuthenticatedRequestsOnly)
                {
                    _options.QueryHandler.HttpProcessorType = typeof(SecureGraphQLHttpProcessor <TSchema>);
                }
                else
                {
                    _options.QueryHandler.HttpProcessorType = typeof(DefaultGraphQLHttpProcessor <TSchema>);
                }
            }

            // register the schema
            _serviceCollection.TryAddSingleton(this.BuildNewSchemaInstance);

            // setup default middleware for each required pipeline
            var queryPipelineHelper = new QueryExecutionPipelineHelper <TSchema>(_schemaBuilder.QueryExecutionPipeline);

            queryPipelineHelper.AddDefaultMiddlewareComponents(_options);

            var fieldPipelineHelper = new FieldExecutionPipelineHelper <TSchema>(_schemaBuilder.FieldExecutionPipeline);

            fieldPipelineHelper.AddDefaultMiddlewareComponents(_options);

            var authPipelineHelper = new FieldAuthorizationPipelineHelper <TSchema>(_schemaBuilder.FieldAuthorizationPipeline);

            authPipelineHelper.AddDefaultMiddlewareComponents(_options);

            // register the DI entries for each pipeline
            _serviceCollection.TryAddSingleton(this.CreatePipelineFactory(_schemaBuilder.FieldExecutionPipeline));
            _serviceCollection.TryAddSingleton(this.CreatePipelineFactory(_schemaBuilder.FieldAuthorizationPipeline));
            _serviceCollection.TryAddSingleton(this.CreatePipelineFactory(_schemaBuilder.QueryExecutionPipeline));

            this.RegisterEngineComponents();
        }
Exemplo n.º 2
0
        /// <summary>
        /// This method is called by the parent options just before it is added to the extensions
        /// collection. Use this method to do any sort of configuration, final default settings etc.
        /// This method represents the last opportunity for the extention options to modify its own required
        /// service collection before being incorporated with the DI container.
        /// </summary>
        /// <param name="options">The parent options which owns this extension.</param>
        public virtual void Configure(SchemaOptions options)
        {
            _primaryOptions = options;
            _primaryOptions.DeclarationOptions.AllowedOperations.Add(GraphCollection.Subscription);

            // enforce a default auth method for the server instance
            // if one was not set explicitly by the developer
            if (!_primaryOptions.AuthorizationOptions.Method.HasValue)
            {
                _primaryOptions.AuthorizationOptions.Method = REQUIRED_AUTH_METHOD;
            }

            // Security requirement for this component
            // --------------------------
            // this component MUST use per request authorization
            // a subscription query is then checked before its registered
            // as opposed to when its executed
            var authMethod = _primaryOptions.AuthorizationOptions.Method;

            if (!authMethod.HasValue || authMethod != REQUIRED_AUTH_METHOD)
            {
                throw new ApolloSubscriptionServerException(
                          $"Invalid Authorization Method. The default, apollo compliant, subscription server requires a \"{REQUIRED_AUTH_METHOD}\" " +
                          $"authorization method. (Current authorization method is \"{_schemaBuilder.Options.AuthorizationOptions.Method}\")");
            }

            // swap out the master providers for the ones that includes
            // support for the subscription action type
            if (!(GraphQLProviders.TemplateProvider is SubscriptionEnabledTemplateProvider))
            {
                GraphQLProviders.TemplateProvider = new SubscriptionEnabledTemplateProvider();
            }

            if (!(GraphQLProviders.GraphTypeMakerProvider is SubscriptionEnabledGraphTypeMakerProvider))
            {
                GraphQLProviders.GraphTypeMakerProvider = new SubscriptionEnabledGraphTypeMakerProvider();
            }

            // Update the query execution pipeline
            // ------------------------------------------
            // wipe out the current execution pipeline and rebuild with subscription creation middleware injected
            _schemaBuilder.QueryExecutionPipeline.Clear();
            var subscriptionQueryExecutionHelper = new SubscriptionQueryExecutionPipelineHelper <TSchema>(_schemaBuilder.QueryExecutionPipeline);

            subscriptionQueryExecutionHelper.AddDefaultMiddlewareComponents(_primaryOptions);

            // Update field execution pipeline
            // -----------------------------
            // because the authorization method may have changed
            // rebuild the field execution pipeline as well.
            // This may happen when no method is declared for 'options.AuthorizationOptions.Method'
            // allowing the defaults to propegate during pipeline creation.            //
            // The default for the basic server is "per field"
            // The required value for subscriptions is "per request"
            _schemaBuilder.FieldExecutionPipeline.Clear();
            var fieldExecutionHelper = new FieldExecutionPipelineHelper <TSchema>(_schemaBuilder.FieldExecutionPipeline);

            fieldExecutionHelper.AddDefaultMiddlewareComponents(_primaryOptions);

            // the primary subscription options for the schema
            this.RequiredServices.Add(new ServiceDescriptor(typeof(SubscriptionServerOptions <TSchema>), this.SubscriptionOptions));

            this.RequiredServices.Add(
                new ServiceDescriptor(
                    typeof(ApolloMessageConverterFactory),
                    typeof(ApolloMessageConverterFactory),
                    ServiceLifetime.Singleton));

            // add the needed apollo's classes as optional services
            // if the user has already added support for their own handlers
            // they will be safely ignored
            this.OptionalServices.Add(
                new ServiceDescriptor(
                    typeof(ISubscriptionServer <TSchema>),
                    this.CreateSubscriptionServer,
                    ServiceLifetime.Singleton));
        }