162 lines
4.0 KiB
JavaScript
162 lines
4.0 KiB
JavaScript
import { derived, writable, get } from "svelte/store"
|
|
import { API } from "api"
|
|
import { admin } from "stores/portal"
|
|
import analytics from "analytics"
|
|
|
|
export function createAuthStore() {
|
|
const auth = writable({
|
|
user: null,
|
|
accountPortalAccess: false,
|
|
tenantId: "default",
|
|
tenantSet: false,
|
|
loaded: false,
|
|
postLogout: false,
|
|
})
|
|
const store = derived(auth, $store => {
|
|
return {
|
|
user: $store.user,
|
|
accountPortalAccess: $store.accountPortalAccess,
|
|
tenantId: $store.tenantId,
|
|
tenantSet: $store.tenantSet,
|
|
loaded: $store.loaded,
|
|
postLogout: $store.postLogout,
|
|
isSSO: !!$store.user?.provider,
|
|
}
|
|
})
|
|
|
|
function setUser(user) {
|
|
auth.update(store => {
|
|
store.loaded = true
|
|
store.user = user
|
|
store.accountPortalAccess = user?.accountPortalAccess
|
|
if (user) {
|
|
store.tenantId = user.tenantId || "default"
|
|
store.tenantSet = true
|
|
}
|
|
return store
|
|
})
|
|
|
|
if (user) {
|
|
analytics
|
|
.activate()
|
|
.then(() => {
|
|
analytics.identify(user._id)
|
|
})
|
|
.catch(() => {
|
|
// This request may fail due to browser extensions blocking requests
|
|
// containing the word analytics, so we don't want to spam users with
|
|
// an error here.
|
|
})
|
|
}
|
|
}
|
|
|
|
async function setOrganisation(tenantId) {
|
|
const prevId = get(store).tenantId
|
|
auth.update(store => {
|
|
store.tenantId = tenantId
|
|
store.tenantSet = !!tenantId
|
|
return store
|
|
})
|
|
if (prevId !== tenantId) {
|
|
// re-init admin after setting org
|
|
await admin.init()
|
|
}
|
|
}
|
|
|
|
async function setInitInfo(info) {
|
|
await API.setInitInfo(info)
|
|
auth.update(store => {
|
|
store.initInfo = info
|
|
return store
|
|
})
|
|
return info
|
|
}
|
|
|
|
function setPostLogout() {
|
|
auth.update(store => {
|
|
store.postLogout = true
|
|
return store
|
|
})
|
|
}
|
|
|
|
async function getInitInfo() {
|
|
const info = await API.getInitInfo()
|
|
auth.update(store => {
|
|
store.initInfo = info
|
|
return store
|
|
})
|
|
return info
|
|
}
|
|
|
|
const actions = {
|
|
checkQueryString: async () => {
|
|
const urlParams = new URLSearchParams(window.location.search)
|
|
if (urlParams.has("tenantId")) {
|
|
const tenantId = urlParams.get("tenantId")
|
|
await setOrganisation(tenantId)
|
|
}
|
|
},
|
|
setOrg: async tenantId => {
|
|
await setOrganisation(tenantId)
|
|
},
|
|
getSelf: async () => {
|
|
// We need to catch this locally as we never want this to fail, even
|
|
// though normally we never want to swallow API errors at the store level.
|
|
// We're either logged in or we aren't.
|
|
// We also need to always update the loaded flag.
|
|
try {
|
|
const user = await API.fetchBuilderSelf()
|
|
setUser(user)
|
|
} catch (error) {
|
|
setUser(null)
|
|
}
|
|
},
|
|
login: async creds => {
|
|
const tenantId = get(store).tenantId
|
|
await API.logIn(tenantId, creds.username, creds.password)
|
|
await actions.getSelf()
|
|
},
|
|
logout: async () => {
|
|
await API.logOut()
|
|
setPostLogout()
|
|
setUser(null)
|
|
await setInitInfo({})
|
|
},
|
|
updateSelf: async fields => {
|
|
await API.updateSelf({ ...fields })
|
|
// Refetch to enrich after update.
|
|
try {
|
|
const user = await API.fetchBuilderSelf()
|
|
setUser(user)
|
|
} catch (error) {
|
|
setUser(null)
|
|
}
|
|
},
|
|
forgotPassword: async email => {
|
|
const tenantId = get(store).tenantId
|
|
await API.requestForgotPassword(tenantId, email)
|
|
},
|
|
resetPassword: async (password, resetCode) => {
|
|
const tenantId = get(store).tenantId
|
|
await API.resetPassword(tenantId, password, resetCode)
|
|
},
|
|
generateAPIKey: async () => {
|
|
return API.generateAPIKey()
|
|
},
|
|
fetchAPIKey: async () => {
|
|
const info = await API.fetchDeveloperInfo()
|
|
return info?.apiKey
|
|
},
|
|
}
|
|
|
|
return {
|
|
subscribe: store.subscribe,
|
|
setOrganisation,
|
|
getInitInfo,
|
|
setInitInfo,
|
|
...actions,
|
|
}
|
|
}
|
|
|
|
export const auth = createAuthStore()
|