Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authorization PR #39

Open
wants to merge 75 commits into
base: authorization-implem
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
11890e3
start branch authorization
tobkle May 21, 2017
f422727
auth code in test/output-app
tobkle May 21, 2017
2ba2f6c
auth end-to-end-test yet without generator
tobkle May 21, 2017
8f86cff
added further authorization tests
tobkle May 28, 2017
ec54b30
reworked and plus authorizedFields()
tobkle Jun 3, 2017
4cb3aa9
User finished before Tweet update
tobkle Jun 4, 2017
95bc453
v0.1
tobkle Jun 4, 2017
392715d
cleanup resolvers
tobkle Jun 4, 2017
087106b
easy auth
tobkle Jun 12, 2017
cd760ae
before simplification
tobkle Jun 14, 2017
8979a86
with authorization folder
tobkle Jun 15, 2017
95edb6f
with authorization folder
tobkle Jun 15, 2017
125617c
removed authorization folder
tobkle Jun 15, 2017
bd45a2c
easier authorization
tobkle Jul 9, 2017
884a8c5
logfile with end-to-end-test
tobkle Jul 9, 2017
e98a412
Pass the logger rather than all the bits it needs
Jul 13, 2017
f621804
Simplify authorized loader.
Jul 13, 2017
151b0b4
Merge pull request #1 from tmeasday/patch-2
tobkle Jul 16, 2017
0e4affa
handle conflicts
tobkle Jul 16, 2017
656c8bf
Merge branch 'tmeasday-patch-1' into authorization
tobkle Jul 16, 2017
e0e6ea9
applied changes
tobkle Jul 16, 2017
957e743
Merge git://github.com/tmeasday/create-graphql-server into authorization
tobkle Jul 16, 2017
9dcdc22
new authorization version from 2017-07-17
tobkle Jul 16, 2017
2e761b1
merged
tobkle Jul 16, 2017
69954ce
merge correction
tobkle Jul 16, 2017
755b224
authorization-simple
tobkle Jul 18, 2017
49cee93
authorization
tobkle Aug 3, 2017
d5a4c32
add-user and authorization prototype
tobkle May 8, 2017
5427807
Revert "add-user and authorization prototype"
tobkle Aug 3, 2017
487277a
Merge branch 'authorization-simple'
tobkle Aug 3, 2017
dc4d1b3
PR adjustments + npm package
tobkle Aug 13, 2017
a1f0e40
harden
tobkle Aug 18, 2017
2e00cc6
prepared for generator
tobkle Aug 18, 2017
fe51626
start branch authorization
tobkle May 21, 2017
d3cc04c
auth code in test/output-app
tobkle May 21, 2017
2119d01
auth end-to-end-test yet without generator
tobkle May 21, 2017
95c1f70
added further authorization tests
tobkle May 28, 2017
53a092e
reworked and plus authorizedFields()
tobkle Jun 3, 2017
835c7db
User finished before Tweet update
tobkle Jun 4, 2017
770ad84
v0.1
tobkle Jun 4, 2017
614e17f
cleanup resolvers
tobkle Jun 4, 2017
807224a
easy auth
tobkle Jun 12, 2017
913aa91
before simplification
tobkle Jun 14, 2017
e458afc
with authorization folder
tobkle Jun 15, 2017
e41e061
with authorization folder
tobkle Jun 15, 2017
757fb43
removed authorization folder
tobkle Jun 15, 2017
aadbe9c
easier authorization
tobkle Jul 9, 2017
f311afd
logfile with end-to-end-test
tobkle Jul 9, 2017
cf68cc4
Pass the logger rather than all the bits it needs
Jul 13, 2017
3188144
Simplify authorized loader.
Jul 13, 2017
66cb5ce
handle conflicts
tobkle Jul 16, 2017
06cfb9b
applied changes
tobkle Jul 16, 2017
0a59e67
new authorization version from 2017-07-17
tobkle Jul 16, 2017
720fbd3
merge correction
tobkle Jul 16, 2017
4f3856b
authorization-simple
tobkle Jul 18, 2017
a39a9ff
authorization
tobkle Aug 3, 2017
4179971
add-user and authorization prototype
tobkle May 8, 2017
c92f598
Revert "add-user and authorization prototype"
tobkle Aug 3, 2017
ab3cb9a
PR adjustments + npm package
tobkle Aug 13, 2017
df1defc
harden
tobkle Aug 18, 2017
2e74271
prepared for generator
tobkle Aug 18, 2017
b894088
after pull upstream/master and rebase upstream/master
tobkle Aug 18, 2017
84ad0cd
merged
tobkle Aug 18, 2017
d12860b
with generator
tobkle Aug 20, 2017
e14762b
remove yarn.lock error
tobkle Aug 25, 2017
5ab4acd
indexOf instead of includes polyfill problem
tobkle Aug 25, 2017
21d10b1
README.md file had changed
tobkle Aug 25, 2017
bf3dcae
without .DS_STORE
tobkle Aug 25, 2017
072171b
moved authorize.js to npm module
tobkle Aug 26, 2017
40fd007
modularize authorize
tobkle Aug 26, 2017
a69684f
with user password hash
tobkle Aug 27, 2017
4323c5d
generator implanted
tobkle Aug 31, 2017
9e2d358
with handlebars templating
tobkle Sep 2, 2017
073de89
with handlebars templating, without debugger
tobkle Sep 2, 2017
d5b7163
refactored: split authorization into packages, which are independent …
tobkle Sep 6, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ dev.sqlite3
db
./output
dist
log/all-logs-readable.log
yarn-error.log

102 changes: 101 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,107 @@ class User {
}
```

### Client side code
## Authorization

create-graphql-server can also handle authorizations. There are two ways to control authorizations:
* Authorization by User-Roles
* Authorization by Document-Roles

**User-Roles** are stored in the User type. They group a number of users together, having all the same authorizations, defined with their role they play. Use it to define a user as a "super-administrator", "administrator", "publisher", "editor" or a "default-user". You are free to define your own names and numbers of User-Roles.

**Document-Roles** are stored in document fields which are referencing a User._id. They are there, to define fine grained authorizations for individual documents based on single user level. Use it to define an "owner", "creator", author" or "coauthor" of a document. Define the authorization they are allowed to do with this specific document. Here, the userId will be stored in the corresponding document field instead. If a user wants the specific authorization, it is tested, if this userId is stored in the document, if so, he gains access, if not, it is not allowed.

You can combine both models to define your authorization logic.

Add authorization logic by using a simple @authorize directive within your type definition. Use the following syntax:
```javascript
type ...
@authorize(
<role1>: [<list of authorizations>]
<role2>: [<list of authorizations>]
<role3>: [<list of authorizations>]
)
...
<fieldname1>: String @authRole("<role1>") // User-Role: Stores the Role name in the User type
<fieldname2>: User @authRole("<role2>") // Document-Role: Stores Single UserId
<fieldname3>: [User] @authRole("<role3>") // Document-Role: Stores Multiple UserIds
...
```

A \<role\> can be any name, you want to use for, to describe the authorizations of a group of users. A user can be assigned this \<role\> in a user type of any \<fieldname\>. You have to mark the relevant field name with the directive @authRole("\<role\>").

A list of authorizations can be:
* create: role is authorized to create a record of this type.
* read: role is authorized to readOne and readMany of this type.
* readOne: role is authorized to only readOne of this type.
* readMany: role is authorized to readMany of this type.
* update: role is authorized to update a record of this type.
* delete: role is authorized to delete a record of this type.

You can add any number of roles within a @authorize directive.

There is one pre-defined User-Role called "world". The world role includes all users, signed-in and not signed-in anonymous users. Use this role to define an authorization-list valid for all users.

#### Example on type User
```javascript
type User

@authorize(
admin: ["create", "read", "update", "delete"] // User-Role
this: ["read", "update", "delete"] // Document-Role
)

{
role: String @authRole("admin")
username: String!

bio: String
notify: Boolean

tweets(minLikes: Int): [Tweet!] @hasMany(as: "author")
liked: [Tweet!] @belongsToMany

following: [User!] @belongsToMany
followers: [User!] @hasAndBelongsToMany(as: "following")
}
```

#### Example on type Tweet

```javascript
type Tweet

@authorize(
admin: ["create", "read", "update", "delete"], // User-Role
world: ["read"] // User-Role
author: ["create", "read", "update", "delete"], // Document-Role
coauthors: ["read", "update"], // Document-Role
)

{
author: User! @unmodifiable @belongsTo @authRole("author")
coauthors: [User] @belongsTo @authRole("coauthors")
body: String!

likers: [User!] @hasAndBelongsToMany(as: "liked")
}
```

If you add these types with the create-graphql-server command-line-interface:
```bash
create-graphql-server add-type path/to/input.graphql
```

It will add automatically the authorization code in the model/\<type\>.js files. Have a look into the generated code or in the test application: "test/output-app/model/User.js".

You can manually change the code to protect also single fields of a type. Do it by the usage of this function:
```javascript
// userRole secretField document
docToInsert = protectFields(me, ['admin'], ['role'], docToInsert, { User: this.context.User });
```
By this, only a User (me) with role "admin" is allowed to access the field "docToInsert.role". For any other user, this field is removed from the docToInsert during the protectFields run.

## Client side code

To create users, simply call your generated `createUser` mutation (you may want to add authorization to the resolver, feel free to modify it).

Expand Down
17 changes: 17 additions & 0 deletions bin/test-model-generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, it } from 'mocha';
import chai, { expect } from 'chai';
import chaiDiff from 'chai-diff';
import fs from 'fs';
import { print } from 'graphql';

import readInput from '../generate/read';
import generateSchema from '../generate/schema';
import generateResolvers from '../generate/resolvers';
import generateModel from '../generate/model';

const input = readInput(`${__dirname}/../test/input/User.graphql`);
const schema = generateSchema(input);
const resolverOutput = generateResolvers(input, schema);
const modelOutput = generateModel(input, schema);

console.log(print(schema));
Loading