mirror of
https://github.com/mollersuite/monofile.git
synced 2024-11-23 06:06:27 -08:00
Compare commits
2 commits
40e7350390
...
5a030684db
Author | SHA1 | Date | |
---|---|---|---|
5a030684db | |||
May | ae4252e898 |
15
src/reset.html
Normal file
15
src/reset.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>reset</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>monofile password reset</h1>
|
||||
<form>
|
||||
<input name="password" type="password">
|
||||
READY... STEADY... <input type="submit" name='FYLE!!!'>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -94,9 +94,11 @@ const validators: {
|
|||
requireProofOfIdentity: true,
|
||||
validator: (actor, target, params, ctx) => {
|
||||
|
||||
const email = params.email.toLowerCase()
|
||||
|
||||
if (!Configuration.mail.enabled) return [501, "email not enabled on instance"]
|
||||
|
||||
if (!params.email) {
|
||||
if (!email) {
|
||||
if (target.email) {
|
||||
sendMail(
|
||||
target.email,
|
||||
|
@ -107,11 +109,11 @@ const validators: {
|
|||
return undefined
|
||||
}
|
||||
|
||||
if (actor.admin) return params.email || undefined
|
||||
if (actor.admin) return email || undefined
|
||||
|
||||
// send verification email
|
||||
|
||||
const tryCode = CodeMgr.code("verifyEmail", target.id, params.email)
|
||||
const tryCode = CodeMgr.code("verifyEmail", target.id, email)
|
||||
|
||||
if (!tryCode.success)
|
||||
return [429, tryCode.error]
|
||||
|
@ -119,12 +121,12 @@ const validators: {
|
|||
const { code } = tryCode
|
||||
|
||||
sendMail(
|
||||
params.email,
|
||||
email,
|
||||
`Hey there, ${target.username} - let's connect your email`,
|
||||
`<b>Hello there!</b> You are recieving this message because you decided to link your email, <span code>${
|
||||
params.email.split("@")[0]
|
||||
email.split("@")[0]
|
||||
}<span style="opacity:0.5">@${
|
||||
params.email.split("@")[1]
|
||||
email.split("@")[1]
|
||||
}</span></span>, to your account, <span username>${
|
||||
target.username
|
||||
}</span>. If you would like to continue, please <a href="https://${ctx.req.header(
|
||||
|
@ -258,6 +260,10 @@ const UserUpdateScheme = z.union([
|
|||
}).strict()
|
||||
])
|
||||
|
||||
const PasswordResetScheme = z.object({
|
||||
email: AccountSchemas.Account.shape.email
|
||||
}).required()
|
||||
|
||||
export default function (files: Files) {
|
||||
router.post("/", scheme(z.object({
|
||||
username: AccountSchemas.Username,
|
||||
|
@ -392,5 +398,35 @@ export default function (files: Files) {
|
|||
})
|
||||
})
|
||||
|
||||
router.post(
|
||||
"/:user/requestPasswordReset",
|
||||
noAPIAccess,
|
||||
scheme(PasswordResetScheme),
|
||||
async (ctx) => {
|
||||
const { email } = ctx.get("parsedScheme") as z.infer<typeof PasswordResetScheme>
|
||||
const actor = ctx.get("account")
|
||||
const target = ctx.get("target")
|
||||
|
||||
if (actor)
|
||||
return ServeError(ctx, 404, "account not found")
|
||||
if (!target.email || email !== target.email)
|
||||
return ServeError(ctx, 401, "bad email")
|
||||
|
||||
const tryCode = CodeMgr.code("recoverAccount", target.id, null, 15*60*1000)
|
||||
|
||||
if (!tryCode.success)
|
||||
return ServeError(ctx, 429, tryCode.error)
|
||||
|
||||
await sendMail(
|
||||
target.email!,
|
||||
"Password reset requested",
|
||||
`A password reset for your account, <span username>${target.username}</span>, has been requested.`
|
||||
+ `Go to https://${ctx.req.header("Host")}/go/verify/${tryCode.code.id} to reset your password.`
|
||||
)
|
||||
|
||||
return ctx.text("email sent")
|
||||
}
|
||||
)
|
||||
|
||||
return router
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import type Files from "../../../lib/files.js"
|
|||
import * as CodeMgr from "../../../lib/codes.js"
|
||||
import { Hono } from "hono"
|
||||
import { getAccount, login } from "../../../lib/middleware.js"
|
||||
import { sendMail } from "../../../lib/mail.js"
|
||||
export let router = new Hono<{
|
||||
Variables: {
|
||||
account: Accounts.Account
|
||||
|
@ -36,5 +37,43 @@ export default function (files: Files) {
|
|||
} else return ServeError(ctx, 404, "code not found")
|
||||
})
|
||||
|
||||
router.get("/reset/:code", getAccount, async (ctx) => {
|
||||
let currentAccount = ctx.get("account")
|
||||
let code = CodeMgr.codes.verifyEmail.byId.get(ctx.req.param("code"))
|
||||
|
||||
if (code) {
|
||||
if (currentAccount != undefined && !code.check(currentAccount.id)) {
|
||||
return ServeError(ctx, 403, "you are logged in on a different account")
|
||||
}
|
||||
|
||||
if (!currentAccount) {
|
||||
let ac = Accounts.getFromId(code.for)
|
||||
if (ac) currentAccount = ac
|
||||
else return ServeError(ctx, 401, "could not locate account")
|
||||
}
|
||||
|
||||
let pwd = ctx.req.query("password")
|
||||
|
||||
if (!pwd) {
|
||||
return ctx.html(
|
||||
await fs.readFile(process.cwd() + "/dist/reset.html", "utf-8")
|
||||
)
|
||||
} else {
|
||||
if (currentAccount.email) {
|
||||
sendMail(
|
||||
currentAccount.email,
|
||||
`Your login details have been updated`,
|
||||
`<b>Hello there!</b> Your password on your account, <span username>${currentAccount.username}</span>, has been successfully reset. ` +
|
||||
`Please update your saved login details accordingly.`
|
||||
).catch()
|
||||
}
|
||||
|
||||
Accounts.password.set(currentAccount.id, pwd)
|
||||
login(ctx, code.for)
|
||||
return ctx.redirect("/")
|
||||
}
|
||||
} else return ServeError(ctx, 404, "code not found")
|
||||
})
|
||||
|
||||
return router
|
||||
}
|
|
@ -12,6 +12,7 @@ export default defineConfig({
|
|||
main: resolve(__dirname, "src/index.html"),
|
||||
download: resolve(__dirname, "src/download.html"),
|
||||
error: resolve(__dirname, "src/error.html"),
|
||||
reset: resolve(__dirname, "src/reset.html"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue