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>
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 password = ""
let email = ""
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>
<div class="login">
@ -15,13 +29,13 @@
</Layout>
<Layout gap="XS" noPadding>
<Heading textAlign="center">Forgotten your password?</Heading>
<Body size="S" textAlign="center"
>No problem! Just enter your account's email address and we'll send
you a link to reset it.</Body
>
<Input label="Email" bind:value={username} />
<Body size="S" textAlign="center">
No problem! Just enter your account's email address and we'll send
you a link to reset it.
</Body>
<Input label="Email" bind:value={email} />
</Layout>
<Button cta on:click={reset}>Reset your password</Button>
<Button cta on:click={forgot} disabled={!email}>Reset your password</Button>
</Layout>
</div>
</div>

View File

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

View File

@ -1,12 +1,23 @@
<script>
import { Input, Button, Layout, Body, Heading } from "@budibase/bbui"
import { params } from "@roxi/routify"
import { Button, Layout, Body, Heading, notifications } from "@budibase/bbui"
import PasswordRepeatInput from "components/common/users/PasswordRepeatInput.svelte"
import { params, goto } from "@roxi/routify"
import { auth } from "stores/backend"
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>
<div class="login">
@ -17,12 +28,12 @@
</Layout>
<Layout gap="XS" noPadding>
<Heading textAlign="center">Reset your password</Heading>
<Body size="S" textAlign="center"
>Please enter the new password you'd like to use.</Body
>
<Input label="Password" bind:value={password} />
<Body size="S" textAlign="center">
Please enter the new password you'd like to use.
</Body>
<PasswordRepeatInput bind:password bind:error />
</Layout>
<Button cta on:click={reset}>Reset your password</Button>
<Button cta on:click={reset} disabled={error || !resetCode}>Reset your password</Button>
</Layout>
</div>
</div>

View File

@ -33,6 +33,25 @@ export function createAuthStore() {
await response.json()
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 => {
const response = await api.post(`/api/admin/users`, user)
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)
}