2023-08-22 05:34:20 +10:00
|
|
|
import { createMachine, assign } from 'xstate'
|
|
|
|
import { Models } from '@kittycad/lib'
|
|
|
|
import withBaseURL from '../lib/withBaseURL'
|
2023-08-28 20:31:49 -04:00
|
|
|
import { CommandBarMeta } from '../lib/commands'
|
2023-08-22 05:34:20 +10:00
|
|
|
|
|
|
|
export interface UserContext {
|
|
|
|
user?: Models['User_type']
|
|
|
|
token?: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export type Events =
|
|
|
|
| {
|
2023-08-28 20:31:49 -04:00
|
|
|
type: 'Log out'
|
2023-08-22 05:34:20 +10:00
|
|
|
}
|
|
|
|
| {
|
2023-08-28 20:31:49 -04:00
|
|
|
type: 'Log in'
|
2023-08-22 05:34:20 +10:00
|
|
|
token?: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export const TOKEN_PERSIST_KEY = 'TOKEN_PERSIST_KEY'
|
|
|
|
const persistedToken = localStorage?.getItem(TOKEN_PERSIST_KEY) || ''
|
|
|
|
|
2023-08-28 20:31:49 -04:00
|
|
|
export const authCommandBarMeta: CommandBarMeta = {
|
|
|
|
'Log in': {
|
|
|
|
hide: 'both',
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-08-22 05:34:20 +10:00
|
|
|
export const authMachine = createMachine<UserContext, Events>(
|
|
|
|
{
|
|
|
|
id: 'Auth',
|
|
|
|
initial: 'checkIfLoggedIn',
|
|
|
|
states: {
|
|
|
|
checkIfLoggedIn: {
|
|
|
|
id: 'check-if-logged-in',
|
|
|
|
invoke: {
|
|
|
|
src: 'getUser',
|
|
|
|
id: 'check-logged-in',
|
|
|
|
onDone: [
|
|
|
|
{
|
|
|
|
target: 'loggedIn',
|
|
|
|
actions: assign({
|
|
|
|
user: (context, event) => event.data,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
onError: [
|
|
|
|
{
|
|
|
|
target: 'loggedOut',
|
|
|
|
actions: assign({
|
|
|
|
user: () => undefined,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
loggedIn: {
|
|
|
|
entry: ['goToIndexPage'],
|
|
|
|
on: {
|
2023-08-28 20:31:49 -04:00
|
|
|
'Log out': {
|
2023-08-22 05:34:20 +10:00
|
|
|
target: 'loggedOut',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
loggedOut: {
|
|
|
|
entry: ['goToSignInPage'],
|
|
|
|
on: {
|
2023-08-28 20:31:49 -04:00
|
|
|
'Log in': {
|
2023-08-22 05:34:20 +10:00
|
|
|
target: 'checkIfLoggedIn',
|
|
|
|
actions: assign({
|
2023-08-28 20:31:49 -04:00
|
|
|
token: (_, event) => {
|
2023-08-22 05:34:20 +10:00
|
|
|
const token = event.token || ''
|
|
|
|
localStorage.setItem(TOKEN_PERSIST_KEY, token)
|
|
|
|
return token
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-08-28 20:31:49 -04:00
|
|
|
schema: { events: {} as { type: 'Log out' } | { type: 'Log in' } },
|
2023-08-22 05:34:20 +10:00
|
|
|
predictableActionArguments: true,
|
|
|
|
preserveActionOrder: true,
|
|
|
|
context: { token: persistedToken },
|
|
|
|
},
|
|
|
|
{
|
|
|
|
actions: {},
|
|
|
|
services: { getUser },
|
|
|
|
guards: {},
|
|
|
|
delays: {},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
async function getUser(context: UserContext) {
|
|
|
|
const url = withBaseURL('/user')
|
|
|
|
const headers: { [key: string]: string } = {
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
}
|
|
|
|
if (!context.token && '__TAURI__' in window) throw 'not log in'
|
|
|
|
if (context.token) headers['Authorization'] = `Bearer ${context.token}`
|
2023-08-29 21:45:40 -04:00
|
|
|
try {
|
|
|
|
const response = await fetch(url, {
|
|
|
|
method: 'GET',
|
|
|
|
credentials: 'include',
|
|
|
|
headers,
|
|
|
|
})
|
|
|
|
const user = await response.json()
|
|
|
|
if ('error_code' in user) throw new Error(user.message)
|
|
|
|
return user
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e)
|
|
|
|
}
|
2023-08-22 05:34:20 +10:00
|
|
|
}
|