Skip to content

Commit b437f26

Browse files
committed
create authenticate machine
1 parent 23cf263 commit b437f26

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import * as CR from 'typings'
2+
import * as G from 'typings/graphql'
3+
import { assign, ActionFunctionMap } from 'xstate'
4+
import client from '../../apollo'
5+
import { setAuthToken } from '../../apollo/auth'
6+
import authenticateMutation from '../../apollo/mutations/authenticate'
7+
import channel from '../../channel'
8+
import onError from '../../../services/sentry/onError'
9+
import { MachineContext, MachineEvent } from './index'
10+
11+
interface AuthenticateData {
12+
editorLogin: {
13+
token: string
14+
user: G.User
15+
}
16+
}
17+
18+
interface AuthenticateVariables {
19+
machineId: string
20+
sessionId: string
21+
editor: 'VSCODE'
22+
}
23+
24+
const actions: ActionFunctionMap<MachineContext, MachineEvent> = {
25+
setEnv: assign({
26+
env: (context: CR.MachineContext, event: CR.MachineEvent) => {
27+
return {
28+
...context.env,
29+
...event.payload.env,
30+
}
31+
},
32+
}),
33+
authenticate: async (context: CR.MachineContext): Promise<void> => {
34+
const result = await client
35+
.mutate<AuthenticateData, AuthenticateVariables>({
36+
mutation: authenticateMutation,
37+
variables: {
38+
machineId: context.env.machineId,
39+
sessionId: context.env.sessionId,
40+
editor: 'VSCODE',
41+
},
42+
})
43+
.catch(error => {
44+
onError(error)
45+
console.log('ERROR: Authentication failed')
46+
console.log(error.message)
47+
let message
48+
if (error.message.match(/Network error:/)) {
49+
message = {
50+
title: 'Network Error',
51+
description: 'Make sure you have an Internet connection. Restart and try again',
52+
}
53+
} else {
54+
message = {
55+
title: 'Server Error',
56+
description: error.message,
57+
}
58+
}
59+
channel.receive({ data: { type: 'ERROR', payload: { error: message } } })
60+
return
61+
})
62+
63+
if (!result || !result.data) {
64+
const error = new Error('Authentication request responded with no data')
65+
console.log(error)
66+
onError(error)
67+
return
68+
}
69+
const { token } = result.data.editorLogin
70+
// add token to headers
71+
setAuthToken(token)
72+
// pass authenticated action back to state machine
73+
channel.receive({ data: { type: 'AUTHENTICATED' } })
74+
},
75+
}
76+
77+
export default actions
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import * as CR from 'typings'
2+
import { Machine } from 'xstate'
3+
import actions from './actions'
4+
5+
export type MachineEvent =
6+
| { type: 'ENV_LOAD'; payload: { env: CR.Environment } }
7+
| { type: 'AUTHENTICATED' }
8+
| { type: 'ERROR'; payload: { error: Error } }
9+
10+
export type StateSchema = {
11+
states: {
12+
LoadEnvironment: {}
13+
Authenticate: {}
14+
Authenticated: {}
15+
}
16+
}
17+
18+
export type MachineContext = {
19+
env: CR.Environment
20+
error: CR.ErrorMessage | null
21+
}
22+
23+
const options = {
24+
actions,
25+
}
26+
27+
export const authenticateMachine = Machine<MachineContext, StateSchema, MachineEvent>(
28+
{
29+
id: 'authenticate',
30+
context: {
31+
error: null,
32+
env: { machineId: '', sessionId: '', token: '' },
33+
},
34+
initial: 'LoadEnvironment',
35+
states: {
36+
LoadEnvironment: {
37+
onEntry: ['loadEnv'],
38+
on: {
39+
ENV_LOAD: {
40+
target: 'Authenticate',
41+
actions: ['setEnv'],
42+
},
43+
},
44+
},
45+
46+
Authenticate: {
47+
onEntry: ['authenticate'],
48+
on: {
49+
AUTHENTICATED: 'Authenticated',
50+
ERROR: {
51+
actions: ['setError'],
52+
},
53+
},
54+
},
55+
Authenticated: {
56+
type: 'final',
57+
},
58+
},
59+
},
60+
options,
61+
)

0 commit comments

Comments
 (0)