This repository has been archived by the owner on May 10, 2024. It is now read-only.
/
callback.js
140 lines (124 loc) · 3.61 KB
/
callback.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import React from 'react';
import gql from 'graphql-tag';
import { compose } from 'react-apollo';
import config from '../../config';
import { popSecret } from '../../util/auth';
import { apolloMutation } from '../../hocs/apollo';
import page from '../../hocs/page';
function onAuthenticated(lock) {
return new Promise(resolve => lock.on('authenticated', resolve));
}
function getProfile(lock, authToken) {
return new Promise((resolve, reject) => {
lock.getProfile(authToken, (error, profile) => (error ? reject(error) : resolve(profile)));
});
}
function checkSecret(actual) {
if (actual !== popSecret()) {
throw new Error('Unexpected auth secret');
}
}
const loginCallback = async () => {
const Auth0Lock = require('auth0-lock').default; // eslint-disable-line global-require
const lock = new Auth0Lock(config.AUTH0_CLIENT_ID, config.AUTH0_DOMAIN);
const { idToken: authToken, state } = await onAuthenticated(lock);
const { secret, nextPathname } = JSON.parse(state);
checkSecret(secret);
return { lock, authToken, nextPathname };
};
// TODO create slug server-side to ensure it is available
function createSlug({ givenName, familyName }) {
return `${givenName.substring(0, 1)}${familyName}`.substring(0, 8).toLowerCase();
}
function createUserDataFromProfile(profile) {
const user = {
givenName: profile.given_name,
familyName: profile.family_name,
picture: profile.picture,
};
user.slug = createSlug(user);
return user;
}
class LoginCallback extends React.Component {
static propTypes = {
createUser: React.PropTypes.func.isRequired,
signInUser: React.PropTypes.func.isRequired,
};
async componentDidMount() {
const { lock, authToken /* , nextPathname */ } = await loginCallback();
const profile = await getProfile(lock, authToken);
/* const userToken = */ await this.createUserIfNeededAndSignIn(authToken, profile);
// TODO
}
async createUserIfNeeded(authToken, profile) {
try {
await this.props.createUser({
variables: {
authToken,
...createUserDataFromProfile(profile),
},
});
} catch (e) {
// 3023 means user was already created, so let's ignore this error
// see https://github.com/graphcool/dashboard/issues/294
if (!e.graphQLErrors || e.graphQLErrors[0].code !== 3023) {
throw e;
}
}
}
async signInUser(authToken) {
const signInUserResponse = await this.props.signInUser({
variables: {
authToken,
},
});
console.log('signInUser response!', signInUserResponse);
return signInUserResponse.signinUser.token;
}
async createUserIfNeededAndSignIn(authToken, profile) {
await this.createUserIfNeeded(authToken, profile);
return await this.signInUser(authToken);
}
render() {
return <span>Welcome back, one moment please...</span>;
}
}
const createUserMutation = gql`
mutation createUser(
$authToken: String!
$givenName: String!
$familyName: String!
$slug: String!
$picture: String!
) {
createUser(
authProvider: {
auth0: {
idToken: $authToken
}
}
givenName: $givenName
familyName: $familyName
slug: $slug
picture: $picture
) {
auth0UserId
}
}
`;
const signInUserMutation = gql`
mutation signInUser($authToken: String!) {
signinUser(
auth0: {
idToken: $authToken
}
) {
token
}
}
`;
const WithMutations = compose(
apolloMutation(signInUserMutation, { name: 'signInUser' }),
apolloMutation(createUserMutation, { name: 'createUser' }),
)(LoginCallback);
export default page(WithMutations);