Skip to content

Commit 53381cb

Browse files
Updated security policy and dates (#39)
* clarifications and rewording * reworked home page and overview page layout * added security file
1 parent f7bc0b7 commit 53381cb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+962
-404
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021 GraphQL ASP.NET
3+
Copyright (c) 2023 GraphQL ASP.NET
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

SECURITY.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Thanks for helping make GraphQL ASP.NET safe for everyone.
2+
3+
We take the security of our library seriously, including all of the open source code repositories managed through our GitHub organization.
4+
5+
## Reporting Security Issues
6+
7+
If you believe you have found a security vulnerability in any of our repositories, please report it to us through coordinated disclosure.
8+
9+
Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.
10+
11+
Instead, please send an email to security@graphql-aspnet.org
12+
13+
Please include as much of the information listed below as you can to help us better understand and resolve the issue:
14+
15+
The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)
16+
Full paths of source file(s) related to the manifestation of the issue if known
17+
The location of the affected source code (tag/branch/commit or direct URL)
18+
Any special configuration required to reproduce the issue
19+
Step-by-step instructions to reproduce the issue
20+
Proof-of-concept or exploit code (if possible)
21+
Impact of the issue, including how an attacker might exploit the issue
22+
23+
This information will help us triage your report more quickly.
24+
25+
Thank you!

docs/advanced/custom-scalars.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ sidebar_label: Custom Scalars
55
sidebar_position: 3
66
---
77

8-
Scalars are the most basic, fundamental unit of content in GraphQL. It is one of two leaf types (the other being [ENUMS](../types/enums)). When a query is resolved the returned data will be a set of nested key/value pairs where every key is a string and every value is either another set of key/value pairs, an enum or a scalar.
8+
Scalars are the most basic, fundamental unit of content in GraphQL. It is one of two leaf types (the other being [enums](../types/enums)).
99

1010
Enums, being a type of their own, are very straight forward in .NET. Scalars, however; can be anything. For instance, the `Uri` scalar is represented in GraphQL by a string. On the server though, we convert it into a `System.Uri` object, with all the extra features that go along with it.
1111

12-
This can be done for any value that can be represented as a simple set of characters. When you create a scalar you declare its .NET type, provide a value resolver that accepts raw data from a query (a `ReadOnlySpan<char>`) and returns the completed scalar value.
12+
This can be done for any value that can be represented as a simple set of characters. When you create a scalar you declare its .NET type, provide a value resolver that accepts raw data from a query (a `ReadOnlySpan<char>`) and returns the instantiated scalar value.
1313

14-
Lets say we wanted to build a scalar called `Money` that can handle both an amount and currency symbol. We might accept it in a query like this:
14+
Lets say we wanted to build a scalar called `Money` that can handle both an amount and currency symbol (e.g. "$23.45"). We might accept it in a query like this:
1515

1616
```csharp title="Declaring a Money Scalar"
1717
public class InventoryController : GraphController
@@ -84,8 +84,8 @@ public interface ILeafValueResolver
8484

8585
### IScalarGraphType Members
8686

87-
- `Name`: The name of this scalar in GraphQL. This is the name that will be displayed in introspection queries.
88-
- `InternalName`: An alternative name representing the scalar in server side code. This name is commonly used in logging messages and exceptions to identify the scalar in terms of the server. Its common to use the fully qualified name, i.e. `"MyNameSpace.Money"`.
87+
- `Name`: The unique name of this scalar. This name must be used when declaring a variable.
88+
- `InternalName`: An alternate name representing the scalar in server side code. This name is commonly used in logging messages and exceptions to identify the scalar in terms of the server definitions. Its common to use the fully qualified name, i.e. `"MyNameSpace.Money"`.
8989
- `Description`: The phrase that will used to describe the scalar in introspection queries.
9090
- `Kind`: Scalars must always be declared as `TypeKind.SCALAR`.
9191
- `Publish`: Indicates if the scalar should be published for introspection queries. Unless there is a very strong reason not to, scalars should always be published. Set this value to `true`.
@@ -95,16 +95,16 @@ public interface ILeafValueResolver
9595
- `OtherKnownTypes`: A collection of other potential types that could be used to represent the scalar in a controller class. For instance, integers can be expressed as `int` or `int?`. Most scalars will provide an empty list (e.g. `TypeCollection.Empty`).
9696
- `SourceResolver`: An object that implements `ILeafValueResolver` which can convert raw input data into the scalar's primary `ObjectType`.
9797
- `Serialize(object)`: A method that converts an instance of your scalar to a leaf value that is serializable in a query response
98-
- This method must return a `number`, `string`, `bool` or `null`.
99-
- When converting to a number this can be any C# number value type (int, float, decimal etc.).
98+
- This method **must** return a `number`, `string`, `bool` or `null`.
99+
- When converting to a number this method can return any C# number value type (int, float, decimal etc.).
100100
- `SerializeToQueryLanguage(object)`: A method that converts an instance of your scalar to a string representing it if it were declared as part of a schema language type definition.
101101
- This method is used when generated default values for field arguments and input object fields via introspection queries.
102102
- This method must return a value exactly as it would appear in a schema type definition For example, strings must be surrounded by quotes.
103103

104-
- `ValidateObject(object)`: A method used when validating data returned from a a field resolver. GraphQL will call this method and provide an object instance to determine if its acceptable and can be used in a query result.
104+
- `ValidateObject(object)`: A method used when validating data received from a a field resolver. GraphQL will call this method and provide an object instance to determine if its acceptable and can be used in a query result.
105105

106106
:::note
107-
`ValidateObject(object)` should not attempt to enforce nullability rules. In general, all scalars "could be null" depending on their usage in a schema. All scalars should return `true` for a validation result if the provided object is `null`.
107+
`ValidateObject(object)` should not attempt to enforce nullability rules. In general, all scalars "could be null" depending on their usage in a schema. All scalars should return `true` for a validation result if the provided object is `null`. A field's type expression, enforced by graphql, will decide if null is acceptable on an individual field.
108108
:::
109109

110110
### ILeafValueResolver
@@ -223,7 +223,7 @@ services.AddGraphQL();
223223
```
224224

225225
:::info
226-
Since our scalar is represented by a .NET class, if we don't pre-register it GraphQL will attempt to parse the `Money` class as an input object graph type. Once registered as a scalar, any attempt to use `Money` as an object graph type will cause an exception.
226+
Since our scalar is represented by a .NET class, if we don't pre-register it, GraphQL will attempt to parse the `Money` class as an input object graph type. Once registered as a scalar, any attempt to use `Money` as an object graph type will cause an exception.
227227
:::
228228

229229
## @specifiedBy Directive
@@ -278,7 +278,7 @@ A few points about designing your scalar:
278278
- Scalar types should be simple and work in isolation.
279279
- The `ReadOnlySpan<char>` provided to `ILeafValueResolver.Resolve` should be all the data needed to generate a value, there should be no need to perform side effects or fetch additional data.
280280
- Scalar types should not track any state, depend on any stateful objects, or attempt to use any sort of dependency injection.
281-
- `ILeafValueResolver.Resolve` must be **FAST**! Since your resolver is used to construct an initial query plan from the raw query text, it'll be called many orders of magnitude more often than any other method.
281+
- `ILeafValueResolver.Resolve` must be **FAST**! Since your resolver is used to construct an initial query plan from the raw query text, it'll be called many orders of magnitude more often than any other method. Taking the time and performing various micro-optimizations are appropriate for this method.
282282

283283
### Aim for Fewer Scalars
284284

docs/advanced/directives.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public class ToUpperDirective : GraphDirective
175175
[DirectiveLocations(DirectiveLocation.FIELD)]
176176
public IGraphActionResult UpdateResolver()
177177
{
178-
if (this.DirectiveTarget as IFieldDocumentPart fieldPart)
178+
if (this.DirectiveTarget is IFieldDocumentPart fieldPart)
179179
{
180180
//
181181
if (fieldPart.Field?.ObjectType != typeof(string))

docs/advanced/graph-action-results.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ public class BakeryController : Controller
1818
Donut donut = null;
1919
// ...
2020
21+
// highlight-start
2122
// return the donut and indicate success
22-
return this.Ok(donut);
23+
return this.Ok(donut);
24+
// highlight-end
2325
}
2426
}
2527
```
@@ -33,13 +35,15 @@ public class BakeryController : Controller
3335
Donut donut = null;
3436
// ...
3537
36-
// return the donut directly!
38+
// highlight-start
39+
// return the donut directly!
3740
return donut;
41+
// highlight-end
3842
}
3943
}
4044
```
4145

42-
You can either return the data itself or some alternate `IActionResult` to tell ASP.NET how to render a response.
46+
> You can either return the data itself or some alternate `IActionResult` to tell ASP.NET how to render a response.
4347
4448
Some common ASP.NET action results:
4549

@@ -48,7 +52,7 @@ Some common ASP.NET action results:
4852
- `this.File()`: Return status 200 and stream the file to the client.
4953
- `this.View()`: Render a razor view and send the HTML to the client.
5054

51-
This works the same way in GraphQL ASP.NET. The available actions are slightly different (GraphQL won't stream files) but the usage is the same. You can even write your own action results.
55+
This works the same way in GraphQL ASP.NET. The available actions are slightly different (e.g. GraphQL won't stream files) but the usage is the same. You can even write your own action results.
5256

5357
## Controller Action Results
5458

@@ -57,10 +61,10 @@ Instead of `IActionResult` we use `IGraphActionResult` from a controller action
5761
Built in Controller Action Methods:
5862

5963
- `this.Ok(fieldValue)` : Return _fieldValue_ as the resolved value of the field and indicate to the runtime that everything completed successfully.
60-
- `this.Error(message)`: Indicates a problem. Child fields are not processed and an error message with the given text and error code is added to the response payload.
64+
- `this.Error(message)`: Indicates a problem. The field will resolve to a `null` value automatically. Child fields are not processed and an error message with the given text and error code is added to the response payload.
6165
- `this.StartBatch()` : Initiates the start a of a new batch. See [batch operations](../controllers/batch-operations.md) for details.
62-
- `this.Unauthorized()`: Indicate the user is not authorized to request the field. A message telling them as such will be added to the result and no child fields will be processed. The field will be returned a `null` value automatically. This is sometimes necessary for data-level validation that can't be readily determined from an `[Authorize]` attribute or query level validation.
63-
- `this.BadRequest()`: Commonly used in conjunction with `this.ModelState`. This result indicates the data supplied to the method is not valid for the operation. If given the model state collection an error for each validation error is rendered.
66+
- `this.Unauthorized()`: Indicate the user is not authorized to request the field. A message telling them as such will be added to the result and no child fields will be processed. The field will resolve to a `null` value automatically. This is sometimes necessary for data-level validation that can't be readily determined from an `[Authorize]` attribute or query level validation.
67+
- `this.BadRequest()`: Commonly used in conjunction with `this.ModelState`. This result indicates the data supplied to the method is not valid for the operation. If given a model state collection, an error for each validation error is rendered.
6468
- `this.InternalServerError()`: Indicates an unintended error, such as an exception occurred. The supplied message will be added to the response and no child fields will be resolved.
6569

6670
### Directive Action Results
@@ -108,7 +112,7 @@ To create a custom result, implement `IGraphActionResult`, which defines a singl
108112
```csharp title="IGraphActionResult.cs"
109113
public interface IGraphActionResult
110114
{
111-
Task Complete(ResolutionContext context);
115+
Task CompleteAsync(ResolutionContext context);
112116
}
113117
```
114118

@@ -134,17 +138,20 @@ Looking at the `UnauthorizedGraphActionResult` is a great example of how to impl
134138
_errorCode = errorCode ?? Constants.ErrorCodes.ACCESS_DENIED;
135139
}
136140

137-
public Task Complete(ResolutionContext context)
141+
public Task CompleteAsync(ResolutionContext context)
138142
{
143+
// add an error message to the response
139144
context.Messages.Critical(
140145
_errorMessage,
141146
_errorCode,
142147
context.Request.Origin);
143148

149+
// instruct graphql to stop processing this field
150+
// and its children
144151
context.Cancel();
145152
return Task.CompletedTask;
146153
}
147154
}
148155
```
149156

150-
The result takes in an optional error message and code, providing defaults if not supplied. Then on `Complete` it adds the message to the context and cancels its execution.
157+
The result takes in an optional error message and code, providing defaults if not supplied. Then on `CompleteAsync` it adds the message to the context and cancels its execution.

docs/advanced/multiple-schema.md

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,54 +12,61 @@ GraphQL ASP.NET supports multiple schemas on the same server out of the box. Eac
1212
To register multiple schemas you'll need to create your own class that implements `ISchema`. While it is possible to implement `ISchema` directly, if you don't require any extra functionality in your schema its easier to just inherit from the default `GraphSchema`. Updating the `Name` and `Description` is highly encouraged as the information is referenced in several different messages and can be very helpful in debugging.
1313

1414
```csharp title="Declaring Custom Schemas"
15+
// highlight-next-line
1516
public class EmployeeSchema : GraphSchema
1617
{
1718
// The schema name may be referenced in some error messages
1819
// and log entries.
1920
public override string Name => "Employee Schema";
2021

2122
// The description is publically available via introspection queries.
22-
public override string Description => "My Custom Schema";
23+
public override string Description => "Employee Related Data";
2324
}
2425

26+
// highlight-next-line
2527
public class CustomerSchema : GraphSchema
2628
{
2729
public override string Name => "Customer Schema";
30+
public override string Description => "Customer Related Data";
2831
}
2932
```
3033

31-
3234
> Implementing `ISchema` and its dependencies from scratch is not a trivial task and is beyond the scope of this documentation.
3335
3436

3537
## Register Each Schema
3638

3739
Each schema can be registered using an overload of `.AddGraphQL()` during startup.
3840

39-
```csharp title="Adding A Custom Schema at Startup"
40-
services.AddGraphQL<EmployeeSchema>();
41-
```
41+
By default, the query handler will attempt to register a schema to `/graphql` as its URL. You'll want to ensure that each schema has its own endpoint by updating individual routes as necessary.
42+
43+
```csharp title="Adding Multiple Schemas"
44+
var builder = WebApplication.CreateBuilder(args);
45+
46+
builder.Services.AddGraphQL<EmployeeSchema>((options) =>
47+
{
48+
// highlight-next-line
49+
options.QueryHandler.Route = "/graphql_employees";
50+
// add assembly or graph type references here
51+
});
4252

43-
### Give Each Schema its Own HTTP Route
53+
builder.Services.AddGraphQL<CustomerSchema>((options) =>
54+
{
55+
// highlight-next-line
56+
options.QueryHandler.Route = "/graphql_customers";
57+
// add assembly or graph type references here
58+
});
4459

45-
The query handler will attempt to register a schema to `/graphql` as its URL by default; you'll want to ensure that each schema has its own endpoint by updating the individual routes.
60+
var app = builder.Build();
4661

47-
```csharp title="Adding Multiple Schemas"
48-
services.AddGraphQL<EmployeeSchema>((options) =>
49-
{
50-
// highlight-next-line
51-
options.QueryHandler.Route = "/graphql_employees";
52-
// add assembly or graph type references here
53-
});
54-
55-
services.AddGraphQL<CustomerSchema>((options) =>
56-
{
57-
// highlight-next-line
58-
options.QueryHandler.Route = "/graphql_customers";
59-
// add assembly or graph type references here
60-
});
62+
// highlight-next-line
63+
app.UseGraphQL();
64+
app.Run();
6165
```
6266

67+
:::note
68+
Each schema **must** be configured to use its own endpoint.
69+
:::
6370

6471
## Disable Local Graph Entity Registration
6572

0 commit comments

Comments
 (0)