diff --git a/src/reset.html b/src/reset.html
new file mode 100644
index 0000000..3b8dd77
--- /dev/null
+++ b/src/reset.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ reset
+
+
+ monofile password reset
+
+
+
\ No newline at end of file
diff --git a/src/server/routes/api/v1/account/index.ts b/src/server/routes/api/v1/account/index.ts
index be0f344..be22775 100644
--- a/src/server/routes/api/v1/account/index.ts
+++ b/src/server/routes/api/v1/account/index.ts
@@ -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`,
`Hello there! You are recieving this message because you decided to link your email, ${
- params.email.split("@")[0]
+ email.split("@")[0]
}@${
- params.email.split("@")[1]
+ email.split("@")[1]
}, to your account, ${
target.username
}. If you would like to continue, please {
+ const { email } = ctx.get("parsedScheme") as z.infer
+ 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, ${target.username}, 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
}
diff --git a/src/server/routes/api/web/go.ts b/src/server/routes/api/web/go.ts
index 782c9f7..92018c8 100644
--- a/src/server/routes/api/web/go.ts
+++ b/src/server/routes/api/web/go.ts
@@ -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
@@ -35,6 +36,44 @@ export default function (files: Files) {
return ctx.redirect('/')
} 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`,
+ `Hello there! Your password on your account, ${currentAccount.username}, 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
}
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index 7cae786..17352ca 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -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"),
},
},
},