Building up the API interactions for the forgotten password flow.

This commit is contained in:
mike12345567 2021-05-18 15:26:09 +01:00
parent 6013cfd8ed
commit e9b9ada128
5 changed files with 66 additions and 115 deletions

View File

@ -1,10 +1,24 @@
<script> <script>
import { Input, Button, Layout, Body, Heading } from "@budibase/bbui" import {
Input,
Button,
Layout,
Body,
Heading,
notifications,
} from "@budibase/bbui"
import { auth } from "stores/backend"
let username = "" let email = ""
let password = ""
async function reset() {} async function forgot() {
try {
await auth.forgotPassword(email)
notifications.success("Email sent - please check your inbox")
} catch (err) {
notifications.error("Unable to send reset password link")
}
}
</script> </script>
<div class="login"> <div class="login">
@ -15,13 +29,13 @@
</Layout> </Layout>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading textAlign="center">Forgotten your password?</Heading> <Heading textAlign="center">Forgotten your password?</Heading>
<Body size="S" textAlign="center" <Body size="S" textAlign="center">
>No problem! Just enter your account's email address and we'll send No problem! Just enter your account's email address and we'll send
you a link to reset it.</Body you a link to reset it.
> </Body>
<Input label="Email" bind:value={username} /> <Input label="Email" bind:value={email} />
</Layout> </Layout>
<Button cta on:click={reset}>Reset your password</Button> <Button cta on:click={forgot} disabled={!email}>Reset your password</Button>
</Layout> </Layout>
</div> </div>
</div> </div>

View File

@ -52,9 +52,9 @@
</Layout> </Layout>
<Layout gap="S" noPadding> <Layout gap="S" noPadding>
<Button cta on:click={login}>Sign in to Budibase</Button> <Button cta on:click={login}>Sign in to Budibase</Button>
<ActionButton quiet on:click={() => $goto("./forgot")} <ActionButton quiet on:click={() => $goto("./forgot")}>
>Forgot password?</ActionButton Forgot password?
> </ActionButton>
</Layout> </Layout>
</Layout> </Layout>
</div> </div>

View File

@ -1,12 +1,23 @@
<script> <script>
import { Input, Button, Layout, Body, Heading } from "@budibase/bbui" import { Button, Layout, Body, Heading, notifications } from "@budibase/bbui"
import { params } from "@roxi/routify" import PasswordRepeatInput from "components/common/users/PasswordRepeatInput.svelte"
import { params, goto } from "@roxi/routify"
import { auth } from "stores/backend" import { auth } from "stores/backend"
const resetCode = $params["?code"] const resetCode = $params["?code"]
let password = "" let password, error
async function reset() {} async function reset() {
try {
await auth.resetPassword(password, resetCode)
notifications.success("Password reset successfully")
// send them to login if reset successful
$goto("./login")
} catch (err) {
notifications.error("Unable to reset password")
}
}
</script> </script>
<div class="login"> <div class="login">
@ -17,12 +28,12 @@
</Layout> </Layout>
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Heading textAlign="center">Reset your password</Heading> <Heading textAlign="center">Reset your password</Heading>
<Body size="S" textAlign="center" <Body size="S" textAlign="center">
>Please enter the new password you'd like to use.</Body Please enter the new password you'd like to use.
> </Body>
<Input label="Password" bind:value={password} /> <PasswordRepeatInput bind:password bind:error />
</Layout> </Layout>
<Button cta on:click={reset}>Reset your password</Button> <Button cta on:click={reset} disabled={error || !resetCode}>Reset your password</Button>
</Layout> </Layout>
</div> </div>
</div> </div>

View File

@ -33,6 +33,25 @@ export function createAuthStore() {
await response.json() await response.json()
store.update(state => ({ ...state, user: null })) store.update(state => ({ ...state, user: null }))
}, },
forgotPassword: async email => {
const response = await api.post(`/api/admin/auth/reset`, {
email,
})
if (response.status !== 200) {
throw "Unable to send email with reset link"
}
await response.json()
},
resetPassword: async (password, code) => {
const response = await api.post(`/api/admin/auth/reset/update`, {
password,
resetCode: code,
})
if (response.status !== 200) {
throw "Unable to reset password"
}
await response.json()
},
createUser: async user => { createUser: async user => {
const response = await api.post(`/api/admin/users`, user) const response = await api.post(`/api/admin/users`, user)
if (response.status !== 200) { if (response.status !== 200) {

View File

@ -1,93 +0,0 @@
const authPkg = require("@budibase/auth")
const { google } = require("@budibase/auth/src/middleware")
const { Configs } = require("../../constants")
const CouchDB = require("../../db")
const { clearCookie } = authPkg.utils
const { Cookies } = authPkg.constants
const { passport } = authPkg.auth
const GLOBAL_DB = authPkg.StaticDatabases.GLOBAL.name
exports.authenticate = async (ctx, next) => {
return passport.authenticate("local", async (err, user) => {
if (err) {
return ctx.throw(403, "Unauthorized")
}
const expires = new Date()
expires.setDate(expires.getDate() + 1)
if (!user) {
return ctx.throw(403, "Unauthorized")
}
ctx.cookies.set(Cookies.Auth, user.token, {
expires,
path: "/",
httpOnly: false,
overwrite: true,
})
delete user.token
ctx.body = { user }
})(ctx, next)
}
exports.logout = async ctx => {
clearCookie(ctx, Cookies.Auth)
ctx.body = { message: "User logged out" }
}
/**
* The initial call that google authentication makes to take you to the google login screen.
* On a successful login, you will be redirected to the googleAuth callback route.
*/
exports.googlePreAuth = async (ctx, next) => {
const db = new CouchDB(GLOBAL_DB)
const config = await authPkg.db.getScopedFullConfig(db, {
type: Configs.GOOGLE,
group: ctx.query.group,
})
const strategy = await google.strategyFactory(config)
return passport.authenticate(strategy, {
scope: ["profile", "email"],
})(ctx, next)
}
exports.googleAuth = async (ctx, next) => {
const db = new CouchDB(GLOBAL_DB)
const config = await authPkg.db.getScopedFullConfig(db, {
type: Configs.GOOGLE,
group: ctx.query.group,
})
const strategy = await google.strategyFactory(config)
return passport.authenticate(
strategy,
{ successRedirect: "/", failureRedirect: "/error" },
async (err, user) => {
if (err) {
return ctx.throw(403, "Unauthorized")
}
const expires = new Date()
expires.setDate(expires.getDate() + 1)
if (!user) {
return ctx.throw(403, "Unauthorized")
}
ctx.cookies.set(Cookies.Auth, user.token, {
expires,
path: "/",
httpOnly: false,
overwrite: true,
})
ctx.redirect("/")
}
)(ctx, next)
}