Skip to content

Commit 3984925

Browse files
author
Robert Mosolgo
authored
Merge pull request rmosolgo#965 from rmosolgo/pro-156
Release graphql-pro 1.5.6
2 parents e1487bf + 96d5778 commit 3984925

File tree

11 files changed

+100
-42
lines changed

11 files changed

+100
-42
lines changed

CHANGELOG-pro.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,22 @@
88

99
### Bug Fix
1010

11+
## 1.5.6 (19 Sept 2017)
12+
13+
### New Features
14+
15+
- Add `authorization(..., operation_store:)` option for authorizing operation store requests
16+
17+
## 1.5.5 (18 Sept 2017)
18+
19+
### New Features
20+
21+
- Support `ConnectionType.bidrectional_pagination?` in stable RelationConnection
22+
1123
## 1.5.4 (18 Sept 2017)
1224

25+
### Bug Fix
26+
1327
- Fix load issue when Rails is not present
1428

1529
## 1.5.3 (4 Sept 2017)

guides/javascript_client/apollo_subscriptions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ var OperationStoreClient = require("./OperationStoreClient")
4343
RailsNetworkInterface.use([OperationStoreClient.apolloMiddleware])
4444
```
4545

46-
See the Subscriptions guide for information about server-side setup.
46+
See the {% internal_link "Subscriptions guide", "/subscriptions/overview" %} for information about server-side setup.

guides/javascript_client/relay_subscriptions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ var subscriptionHandler = createHandler({
3131
var network = Network.create(fetchQuery, subscriptionHandler)
3232
```
3333

34-
See the Subscriptions guide for information about server-side setup.
34+
See the {% internal_link "Subscriptions guide", "/subscriptions/overview" %} for information about server-side setup.

guides/javascript_client/sync.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ JavaScript support for GraphQL projects using [graphql-pro](http://graphql.pro)'
1515
- [Plain JS support](#use-with-plain-javascript)
1616
- [Authorization](#authorization)
1717

18-
See the [server-side docs on http://graphql-ruby.org](http://graphql-ruby.org/operation_store/overview)
18+
See the {% internal_link "OperationStore guide", "/operation_store/overview" %} for server-side setup.
1919

2020
## `sync` utility
2121

@@ -36,10 +36,10 @@ Generating client module in app/javascript/graphql/OperationStoreClient.js...
3636

3737
option | description
3838
--------|----------
39-
`--url` | [Sync API](http://graphql-ruby.org/operation_store/getting_started.html#add-routes) url
39+
`--url` | {% internal_link "Sync API", "/operation_store/getting_started.html#add-routes" %} url
4040
`--path` | Local directory to search for `.graphql` / `.graphql.js` files
41-
`--client` | Client ID ([created on server](http://graphql-ruby.org/operation_store/client_workflow))
42-
`--secret` | Client Secret ([created on server](http://graphql-ruby.org/operation_store/client_workflow))
41+
`--client` | Client ID ({% internal_link "created on server", "/operation_store/client_workflow" %})
42+
`--secret` | Client Secret ({% internal_link "created on server", "/operation_store/client_workflow" %})
4343
`--outfile` | Destination for generated JS code
4444

4545
You can see these and a few others with `graphql-ruby-client sync --help`.
@@ -140,7 +140,7 @@ $.post("/graphql", {
140140

141141
## Authorization
142142

143-
`OperationStore` uses HMAC-SHA256 to [authenticate requests](http://graphql-ruby.org/operation_store/authentication).
143+
`OperationStore` uses HMAC-SHA256 to {% internal_link "authenticate requests" , "/operation_store/access_control" %}.
144144

145145
Pass the key to `graphql-ruby-client sync` as `--secret` to authenticate it:
146146

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
layout: guide
3+
search: true
4+
section: GraphQL Pro - OperationStore
5+
title: Access Control
6+
desc: Manage authentication & visibility for your OperationStore server.
7+
index: 4
8+
---
9+
10+
There are two considerations for incoming `sync` requests:
11+
12+
- __Authentication__: is this request coming from a legitimate source?
13+
- __Authorization__: does this source have permission to save these queries?
14+
15+
## Authentication
16+
17+
When you [add a client]({{ site.base_url }}/operation_store/client_workflow#add-a-client), you also associate a _secret_ with that client. You can use the default or provide your own and you can update a client secret at any time. By updating a secret, old secrets become invalid.
18+
19+
This secret is used to add an authorization header, generated with HMAC-SHA256. With this header, the server can assert:
20+
21+
- The request came from an authorized client
22+
- The request was not corrupted in transit
23+
24+
For more info about HMAC, see [Wikipedia](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code) or Ruby's [OpenSSL::HMAC](https://ruby-doc.org/stdlib-2.4.0/libdoc/openssl/rdoc/OpenSSL/HMAC.html) support.
25+
26+
The Authorization header takes the form:
27+
28+
```ruby
29+
"GraphQL::Pro #{client_name} #{hmac}"
30+
```
31+
32+
[`graphql-ruby-client`](http://github.com/rmosolgo/graphql-ruby-client) adds this header to outgoing requests by using the provided `--client` and `--secret` values.
33+
34+
## Authorization
35+
36+
Incoming operations are validated. If you're using `GraphQL::Pro`'s {% internal_link "visibility authorization", "/pro/authorization#visibility-authorization" %}, you must determine whether the current client can _see_ the types and fields which are used in the operation.
37+
38+
You can implement authorization for incoming queries with the `authorize(..., operation_store:)` option, which accepts a {% internal_link "auth strategy class", "/pro/authorization#custom-authorization-strategy" %}, for example:
39+
40+
```ruby
41+
authorize(:pundit, operation_store: OperationStoreStrategy)
42+
# Or:
43+
authorize(MyAuthStrategy, operation_store: OperationStoreStrategy)
44+
```
45+
46+
This strategy class is used _only_ for incoming persisted operations. The strategy class may use `ctx[:current_client_name]`, which is added by the OperationStore.
47+
48+
Here's an example strategy class which allows `"stafftools"` apps to use `view: :admin` fields, but hides those fields from everyone else:
49+
50+
```ruby
51+
class OperationStoreStrategy
52+
def initialize(ctx)
53+
@client_name = ctx[:current_client_name]
54+
end
55+
56+
# Only stafftools apps can save queries with `:admin` fields
57+
# Anyone can save queries with `:public` fields.
58+
def allowed?(gate, _obj)
59+
case gate.role
60+
when :admin
61+
@client_name == "stafftools"
62+
when :public
63+
true
64+
else
65+
raise "Unexpected auth role: #{gate.role}"
66+
end
67+
end
68+
end
69+
```
70+
71+
If you don't specify a strategy, the default is to fail all `view:` checks. This way, private fields are _not_ disclosed via OperationStore requests.

guides/operation_store/authentication.md

Lines changed: 0 additions & 25 deletions
This file was deleted.

guides/operation_store/client_workflow.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Clients are registered via {% internal_link "the UI","/operation_store/getting_s
2222

2323
{{ "/operation_store/add_a_client.png" | link_to_img:"Add a Client for Persisted Queries" }}
2424

25-
A default `secret` is provided for you, but you can also enter your own. The `secret` is used for {% internal_link "HMAC authentication", "/operation_store/authentication" %}.
25+
A default `secret` is provided for you, but you can also enter your own. The `secret` is used for {% internal_link "HMAC authentication", "/operation_store/access_control" %}.
2626

2727
(Are you interested in a Ruby API for this? Please {% open_an_issue "OperationStore Ruby API" %} or email `[email protected]`.)
2828

@@ -35,7 +35,7 @@ The easiest way to sync is with `graphql-ruby-client sync`, a command-line tool
3535
In short, it:
3636

3737
- Finds GraphQL queries from `.graphql` files or `relay-compiler` output in the provided `--path`
38-
- Adds an {% internal_link "Authentication header","/operation_store/authentication" %} based on the provided `--client` and `--secret`
38+
- Adds an {% internal_link "Authentication header","/operation_store/access_control" %} based on the provided `--client` and `--secret`
3939
- Sends the operations to the provided `--url`
4040
- Generates a JavaScript module into the provided `--outfile`
4141

@@ -68,4 +68,4 @@ The server will use those values to fetch an operation from the database.
6868

6969
#### Next Steps
7070

71-
Learn more about `OperationStore`'s {% internal_link "authentication", "/operation_store/authentication" %} or read some tips for {% internal_link "server management","/operation_store/server_management" %}.
71+
Learn more about `OperationStore`'s {% internal_link "authentication", "/operation_store/access_control" %} or read some tips for {% internal_link "server management","/operation_store/server_management" %}.

guides/operation_store/overview.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ In other guides, you can read more about:
1919

2020
- {% internal_link "Getting Started","/operation_store/getting_started" %} installing `OperationStore` in your app
2121
- {% internal_link "Workflow","/operation_store/client_workflow" %} and usage for client apps
22-
- {% internal_link "Authentication","/operation_store/authentication" %} for the sync API
22+
- {% internal_link "Authentication","/operation_store/access_control" %} for the sync API
2323
- {% internal_link "Server Management","/operation_store/server_management" %} after your system is running
2424

2525
### What are Persisted Queries?
@@ -101,7 +101,7 @@ Persisted queries improve _visibility_ because you can track GraphQL usage from
101101

102102
`OperationStore` uses tables in your database to store normalized, deduplicated GraphQL strings. The database is immutable: new operations may be added, but operations are never modified or removed.
103103

104-
When clients {% internal_link "sync their operations","/operation_store/client_workflow" %}, requests are {% internal_link "authenticated","/operation_store/authentication" %}, then the incoming GraphQL is validated, normalized, and added to the database if needed. Also, the incoming client name is associated with all operations in the payload.
104+
When clients {% internal_link "sync their operations","/operation_store/client_workflow" %}, requests are {% internal_link "authenticated","/operation_store/access_control" %}, then the incoming GraphQL is validated, normalized, and added to the database if needed. Also, the incoming client name is associated with all operations in the payload.
105105

106106
Then, at runtime, clients send an _operation ID_ to run a persisted query. It looks like this in `params`:
107107

guides/pro/authorization.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -335,11 +335,7 @@ You can provide custom authorization logic by providing a class:
335335

336336
```ruby
337337
MySchema = GraphQL::Schema.define do
338-
# choose one:
339-
authorization(:pundit)
340-
# or:
341-
authorization(:cancan)
342-
# or:
338+
# Custom authorization strategy class:
343339
authorization(MyAuthStrategy)
344340
end
345341
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8657b73725fe9390deeaf37f5d6a902cbd2939f8039a9ef0e96d3a7000ab5f835023aa323dad399ef8a00c8686dca5397295b8aadaa9367105976720c9dc9e61
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
928afc8c4526b1869a9e88b2e62115a97d9a062e5bc36a3393a85d887a038da293a08e9baa828d6121a1d0a03974aff7b91bed7cb38d30ebe5dbb5e3e8f96cf7

0 commit comments

Comments
 (0)