Add base auth & ucan request flow (web only)

This commit is contained in:
Paul Frazee 2022-06-14 14:29:47 -05:00
parent 09b78a4634
commit cef133031e
14 changed files with 1555 additions and 290 deletions

View file

@ -4,14 +4,18 @@
*/
import {getEnv, IStateTreeNode} from 'mobx-state-tree'
import * as auth from '@adxp/auth'
import {API} from '../api'
export class Environment {
api = new API()
authStore?: auth.BrowserStore
constructor() {}
async setup() {}
async setup() {
this.authStore = await auth.BrowserStore.load()
}
}
/**

View file

@ -6,6 +6,7 @@ import {
} from './models/root-store'
import {Environment} from './env'
import * as storage from './storage'
import * as auth from '../api/auth'
const ROOT_STATE_STORAGE_KEY = 'root'
@ -14,6 +15,7 @@ export async function setupState() {
let data: any
const env = new Environment()
await env.setup()
try {
data = (await storage.load(ROOT_STATE_STORAGE_KEY)) || {}
rootStore = RootStoreModel.create(data, env)
@ -27,6 +29,16 @@ export async function setupState() {
storage.save(ROOT_STATE_STORAGE_KEY, snapshot),
)
if (env.authStore) {
const isAuthed = await auth.isAuthed(env.authStore)
rootStore.session.setAuthed(isAuthed)
const ucan = await auth.parseUrlForUcan()
if (ucan) {
await env.authStore.addUcan(ucan)
rootStore.session.setAuthed(true)
}
}
return rootStore
}

View file

@ -1,12 +1,13 @@
import {Instance, SnapshotOut, types, flow} from 'mobx-state-tree'
import {UserConfig} from '../../api'
// import {UserConfig} from '../../api'
import * as auth from '../../api/auth'
import {withEnvironment} from '../env'
export const SessionModel = types
.model('Session')
.props({
isAuthed: types.boolean,
uiState: types.enumeration('idle', ['idle', 'working']),
uiIsProcessing: types.maybe(types.boolean),
uiError: types.maybe(types.string),
// TODO: these should be stored somewhere secret
@ -14,56 +15,84 @@ export const SessionModel = types
secretKeyStr: types.maybe(types.string),
rootAuthToken: types.maybe(types.string),
})
.views(self => ({
get hasAccount() {
return self.serverUrl && self.secretKeyStr && self.rootAuthToken
},
}))
.extend(withEnvironment)
.actions(self => ({
setAuthed: (v: boolean) => {
self.isAuthed = v
},
loadAccount: flow(function* () {
if (!self.hasAccount) {
return false
}
self.uiState = 'working'
login: flow(function* () {
self.uiIsProcessing = true
self.uiError = undefined
try {
const cfg = yield UserConfig.hydrate({
serverUrl: self.serverUrl,
secretKeyStr: self.secretKeyStr,
rootAuthToken: self.rootAuthToken,
})
self.environment.api.setUserCfg(cfg)
if (!self.environment.authStore) {
throw new Error('Auth store not initialized')
}
const res = yield auth.requestAppUcan(self.environment.authStore)
self.isAuthed = res
self.uiIsProcessing = false
return res
} catch (e: any) {
console.error('Failed to request app ucan', e)
self.uiError = e.toString()
self.uiIsProcessing = false
return false
}
}),
logout: flow(function* () {
self.uiIsProcessing = true
self.uiError = undefined
try {
if (!self.environment.authStore) {
throw new Error('Auth store not initialized')
}
const res = yield auth.logout(self.environment.authStore)
self.isAuthed = false
self.uiIsProcessing = false
return res
} catch (e: any) {
console.error('Failed to log out', e)
self.uiError = e.toString()
self.uiIsProcessing = false
return false
}
}),
/*loadAccount: flow(function* () {
self.uiIsProcessing = true
self.uiError = undefined
try {
// const cfg = yield UserConfig.hydrate({
// serverUrl: self.serverUrl,
// secretKeyStr: self.secretKeyStr,
// rootAuthToken: self.rootAuthToken,
// })
// self.environment.api.setUserCfg(cfg)
self.isAuthed = true
self.uiState = 'idle'
self.uiIsProcessing = false
return true
} catch (e: any) {
console.error('Failed to create test account', e)
self.uiError = e.toString()
self.uiState = 'idle'
self.uiIsProcessing = false
return false
}
}),
createTestAccount: flow(function* (serverUrl: string) {
self.uiState = 'working'
createTestAccount: flow(function* (_serverUrl: string) {
self.uiIsProcessing = true
self.uiError = undefined
try {
const cfg = yield UserConfig.createTest(serverUrl)
const state = yield cfg.serialize()
self.serverUrl = state.serverUrl
self.secretKeyStr = state.secretKeyStr
self.rootAuthToken = state.rootAuthToken
// const cfg = yield UserConfig.createTest(serverUrl)
// const state = yield cfg.serialize()
// self.serverUrl = state.serverUrl
// self.secretKeyStr = state.secretKeyStr
// self.rootAuthToken = state.rootAuthToken
self.isAuthed = true
self.environment.api.setUserCfg(cfg)
// self.environment.api.setUserCfg(cfg)
} catch (e: any) {
console.error('Failed to create test account', e)
self.uiError = e.toString()
}
self.uiState = 'idle'
}),
self.uiIsProcessing = false
}),*/
}))
export interface Session extends Instance<typeof SessionModel> {}