Skip to content

Commit afec3cd

Browse files
committed
add live demo
fixes #37
1 parent 808a67a commit afec3cd

File tree

16 files changed

+2834
-0
lines changed

16 files changed

+2834
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ node_modules
22
dist
33
*.log
44
coverage
5+
.env

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ A very opinionated user authentication package for [GraphQL](https://graphql.org
77
This package provides **a GraphQL schema and GraphQL resolvers** for everything you need related to authentication. It does not access your data layer (e.g. an ORM); for that you need to write an _adapter_ (which is not hard to do).
88
If you use Prisma, there is already an adapter for you, **[graphql-authentication-prisma](https://github.com/Volst/graphql-authentication/tree/master/packages/graphql-authentication-prisma)**. You can also checkout the [`examples/`](https://github.com/Volst/graphql-authentication/tree/master/examples) folder with examples on how to write an adapter for Sequelize and TypeORM!
99

10+
[**👉 Try out the live demo**](https://graphql-authentication-demo.now.sh/)
11+
1012
**Features:**
1113

1214
- Signup with good ol' email/password and confirmation email

live-demo/.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
MAILGUN_API_KEY=
2+
MAILGUN_DOMAIN=
3+
MAIL_FROM=

live-demo/InMemoryAdapter.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
class GraphqlAuthenticationInMemoryAdapter {
2+
constructor() {
3+
this.users = [];
4+
}
5+
// If you'd use a database you wouldn't need this
6+
_generateId() {
7+
const lastUser = this.users[this.users.length - 1];
8+
if (lastUser) {
9+
return String(parseInt(lastUser.id) + 1);
10+
}
11+
return '1';
12+
}
13+
14+
findUserById(ctx, id, info) {
15+
return Promise.resolve(this.users.find(user => user.id === id) || null);
16+
}
17+
findUserByEmail(ctx, email, info) {
18+
return Promise.resolve(
19+
this.users.find(user => user.email === email) || null
20+
);
21+
}
22+
async userExistsByEmail(ctx, email) {
23+
return Promise.resolve(this.users.some(user => user.email === email));
24+
}
25+
26+
_createUser(ctx, data) {
27+
const user = { id: this._generateId(), ...data };
28+
this.users.push(user);
29+
return Promise.resolve(user);
30+
}
31+
async _updateUser(ctx, userId, data) {
32+
const user = await this.findUserById(ctx, userId);
33+
Object.assign(user, data);
34+
return Promise.resolve(user);
35+
}
36+
37+
createUserBySignup(ctx, data) {
38+
return this._createUser(ctx, data);
39+
}
40+
createUserByInvite(ctx, data) {
41+
return this._createUser(ctx, data);
42+
}
43+
updateUserConfirmToken(ctx, userId, data) {
44+
return this._updateUser(ctx, userId, data);
45+
}
46+
updateUserLastLogin(ctx, userId, data) {
47+
return this._updateUser(ctx, userId, data);
48+
}
49+
updateUserPassword(ctx, userId, data) {
50+
return this._updateUser(ctx, userId, data);
51+
}
52+
updateUserResetToken(ctx, userId, data) {
53+
return this._updateUser(ctx, userId, data);
54+
}
55+
updateUserInfo(ctx, userId, data) {
56+
return this._updateUser(ctx, userId, data);
57+
}
58+
updateUserCompleteInvite(ctx, userId, data) {
59+
return this._updateUser(ctx, userId, data);
60+
}
61+
}
62+
63+
module.exports = { GraphqlAuthenticationInMemoryAdapter };

live-demo/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Live Demo
2+
3+
The code in this repository is used to host a live demo on x.now.sh (TODO).
4+
5+
The live demo uses an in-memory adapter, so everytime the server restarts the data is gone. For a demo this is perfect :).
6+
7+
## Test locally
8+
9+
Run `yarn && yarn start`.
10+
11+
## Deploy on Now
12+
13+
Copy `.env.example` to `.env` and fill the variables in.
14+
15+
```
16+
npm i -g now
17+
now --dotenv
18+
now alias graphql-authentication-demo.now.sh
19+
```

live-demo/email.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const { createTransport } = require('nodemailer');
2+
const mailgun = require('nodemailer-mailgun-transport');
3+
const Email = require('email-templates');
4+
5+
const apiKey = process.env.MAILGUN_API_KEY;
6+
7+
const mailgunConfig = {
8+
auth: {
9+
api_key: apiKey,
10+
domain: process.env.MAILGUN_DOMAIN
11+
}
12+
};
13+
14+
// Just send the email locally if apikey is not filled in
15+
const transporter = apiKey
16+
? createTransport(mailgun(mailgunConfig))
17+
: undefined;
18+
19+
email = new Email({
20+
message: {
21+
from: process.env.MAIL_FROM
22+
},
23+
send: true,
24+
transport: transporter
25+
});
26+
27+
module.exports = { email };

live-demo/emails/inviteUser/html.pug

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
p Hi,
2+
p You are invited to join GraphQL Authentication Demo! Accept the invite by writing this mutation:
3+
pre
4+
| mutation {
5+
| signupByInvite(
6+
| data: {
7+
| name: "Enter your name here",
8+
| password: "myverystrongpassword",
9+
| email: "#{email}",
10+
| inviteToken: "#{inviteToken}"
11+
| }
12+
| ) {
13+
| token
14+
| }
15+
| }
16+
17+
p
18+
em In a real-world application the user wouldn't have to run the mutation itself of course, it would something like this:<br />
19+
a(href=mailAppUrl + '/register/' + email + '/' + inviteToken) Accept invite.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
= `Invited for GraphQL Authentication Demo!`
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
p Hi,
2+
p You requested a password reset on GraphQL Authentication Demo. Reset your password by writing this mutation:
3+
pre
4+
| mutation {
5+
| passwordReset(password: "mynewpassword", email: "#{email}", resetToken: "#{resetToken}") {
6+
| id
7+
| }
8+
|}
9+
10+
p
11+
em In a real-world application the user wouldn't have to run the mutation itself of course, it would something like this:<br />
12+
a(href=mailAppUrl + '/login/reset-password/' + email + '/' + resetToken) Reset my password.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
= `Confirm your email on GraphQL Authentication Demo`

0 commit comments

Comments
 (0)