Convert auth store to TS and add missing user properties
This commit is contained in:
parent
d0b8ab79e3
commit
d72e5f1812
|
@ -36,10 +36,7 @@
|
||||||
await API.createAdminUser(adminUser)
|
await API.createAdminUser(adminUser)
|
||||||
notifications.success("Admin user created")
|
notifications.success("Admin user created")
|
||||||
await admin.init()
|
await admin.init()
|
||||||
await auth.login({
|
await auth.login(formData?.email.trim(), formData?.password)
|
||||||
username: formData?.email.trim(),
|
|
||||||
password: formData?.password,
|
|
||||||
})
|
|
||||||
$goto("../portal")
|
$goto("../portal")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
submitted = false
|
submitted = false
|
||||||
|
|
|
@ -35,10 +35,7 @@
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await auth.login({
|
await auth.login(formData?.username.trim(), formData?.password)
|
||||||
username: formData?.username.trim(),
|
|
||||||
password: formData?.password,
|
|
||||||
})
|
|
||||||
if ($auth?.user?.forceResetPassword) {
|
if ($auth?.user?.forceResetPassword) {
|
||||||
$goto("./reset")
|
$goto("./reset")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -66,10 +66,7 @@
|
||||||
|
|
||||||
async function login() {
|
async function login() {
|
||||||
try {
|
try {
|
||||||
await auth.login({
|
await auth.login(formData.email.trim(), formData.password.trim())
|
||||||
username: formData.email.trim(),
|
|
||||||
password: formData.password.trim(),
|
|
||||||
})
|
|
||||||
notifications.success("Logged in successfully")
|
notifications.success("Logged in successfully")
|
||||||
$goto("../portal")
|
$goto("../portal")
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
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()
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
import { get } from "svelte/store"
|
||||||
|
import { API } from "api"
|
||||||
|
import { admin } from "stores/portal"
|
||||||
|
import analytics from "analytics"
|
||||||
|
import BudiStore from "stores/BudiStore"
|
||||||
|
import {
|
||||||
|
isSSOUser,
|
||||||
|
SetInitInfoRequest,
|
||||||
|
UpdateSelfRequest,
|
||||||
|
User,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
|
interface PortalAuthStore {
|
||||||
|
user?: User
|
||||||
|
initInfo?: Record<string, any>
|
||||||
|
accountPortalAccess: boolean
|
||||||
|
loaded: boolean
|
||||||
|
isSSO: boolean
|
||||||
|
tenantId: string
|
||||||
|
tenantSet: boolean
|
||||||
|
postLogout: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthStore extends BudiStore<PortalAuthStore> {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
accountPortalAccess: false,
|
||||||
|
tenantId: "default",
|
||||||
|
tenantSet: false,
|
||||||
|
loaded: false,
|
||||||
|
postLogout: false,
|
||||||
|
isSSO: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setUser(user?: User) {
|
||||||
|
this.set({
|
||||||
|
loaded: true,
|
||||||
|
user: user,
|
||||||
|
accountPortalAccess: !!user?.accountPortalAccess,
|
||||||
|
tenantId: user?.tenantId || "default",
|
||||||
|
tenantSet: !!user,
|
||||||
|
isSSO: user != null && isSSOUser(user),
|
||||||
|
postLogout: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
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 setOrganisation(tenantId: string) {
|
||||||
|
const prevId = get(this.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 setInitInfo(info: SetInitInfoRequest) {
|
||||||
|
await API.setInitInfo(info)
|
||||||
|
auth.update(store => {
|
||||||
|
store.initInfo = info
|
||||||
|
return store
|
||||||
|
})
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
setPostLogout() {
|
||||||
|
auth.update(store => {
|
||||||
|
store.postLogout = true
|
||||||
|
return store
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async getInitInfo() {
|
||||||
|
const info = await API.getInitInfo()
|
||||||
|
auth.update(store => {
|
||||||
|
store.initInfo = info
|
||||||
|
return store
|
||||||
|
})
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkQueryString() {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
const tenantId = urlParams.get("tenantId")
|
||||||
|
if (tenantId) {
|
||||||
|
await this.setOrganisation(tenantId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async setOrg(tenantId: string) {
|
||||||
|
await this.setOrganisation(tenantId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSelf() {
|
||||||
|
// 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()
|
||||||
|
this.setUser(user)
|
||||||
|
} catch (error) {
|
||||||
|
this.setUser()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async login(username: string, password: string) {
|
||||||
|
const tenantId = get(this.store).tenantId
|
||||||
|
await API.logIn(tenantId, username, password)
|
||||||
|
await this.getSelf()
|
||||||
|
}
|
||||||
|
|
||||||
|
async logout() {
|
||||||
|
await API.logOut()
|
||||||
|
this.setPostLogout()
|
||||||
|
this.setUser()
|
||||||
|
await this.setInitInfo({})
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateSelf(fields: UpdateSelfRequest) {
|
||||||
|
await API.updateSelf(fields)
|
||||||
|
// Refetch to enrich after update.
|
||||||
|
try {
|
||||||
|
const user = await API.fetchBuilderSelf()
|
||||||
|
this.setUser(user)
|
||||||
|
} catch (error) {
|
||||||
|
this.setUser()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async forgotPassword(email: string) {
|
||||||
|
const tenantId = get(this.store).tenantId
|
||||||
|
await API.requestForgotPassword(tenantId, email)
|
||||||
|
}
|
||||||
|
|
||||||
|
async resetPassword(password: string, resetCode: string) {
|
||||||
|
const tenantId = get(this.store).tenantId
|
||||||
|
await API.resetPassword(tenantId, password, resetCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateAPIKey() {
|
||||||
|
return API.generateAPIKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchAPIKey() {
|
||||||
|
const info = await API.fetchDeveloperInfo()
|
||||||
|
return info?.apiKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const auth = new AuthStore()
|
|
@ -70,6 +70,8 @@ export interface User extends Document {
|
||||||
appFavourites?: string[]
|
appFavourites?: string[]
|
||||||
ssoId?: string
|
ssoId?: string
|
||||||
appSort?: string
|
appSort?: string
|
||||||
|
budibaseAccess?: boolean
|
||||||
|
accountPortalAccess?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserBindings extends Document {
|
export interface UserBindings extends Document {
|
||||||
|
|
Loading…
Reference in New Issue