fixing js errors, adding password change form
This commit is contained in:
parent
e89511b14c
commit
f3879cb013
|
@ -44,8 +44,8 @@ async function getFmtInstance() {
|
||||||
return fmtInstance ??= (await fmtInstaceFuture).instance;
|
return fmtInstance ??= (await fmtInstaceFuture).instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {WebAssembly.Instance} instance @param {string} code @param {"fmt" | "minify"} action
|
/** @param {WebAssembly.Instance} instance @param {string} code @param {"tok" | "fmt" | "minify"} action
|
||||||
* @returns {string | undefined} */
|
* @returns {string | Uint8Array | undefined} */
|
||||||
function modifyCode(instance, code, action) {
|
function modifyCode(instance, code, action) {
|
||||||
let {
|
let {
|
||||||
INPUT, INPUT_LEN,
|
INPUT, INPUT_LEN,
|
||||||
|
@ -54,6 +54,7 @@ function modifyCode(instance, code, action) {
|
||||||
} = instance.exports;
|
} = instance.exports;
|
||||||
|
|
||||||
let funs = { fmt, tok, minify };
|
let funs = { fmt, tok, minify };
|
||||||
|
let fun = funs[action];
|
||||||
if (!(true
|
if (!(true
|
||||||
&& memory instanceof WebAssembly.Memory
|
&& memory instanceof WebAssembly.Memory
|
||||||
&& INPUT instanceof WebAssembly.Global
|
&& INPUT instanceof WebAssembly.Global
|
||||||
|
@ -61,9 +62,8 @@ function modifyCode(instance, code, action) {
|
||||||
&& OUTPUT instanceof WebAssembly.Global
|
&& OUTPUT instanceof WebAssembly.Global
|
||||||
&& OUTPUT_LEN instanceof WebAssembly.Global
|
&& OUTPUT_LEN instanceof WebAssembly.Global
|
||||||
&& funs.hasOwnProperty(action)
|
&& funs.hasOwnProperty(action)
|
||||||
&& typeof funs[action] === "function"
|
&& typeof fun === "function"
|
||||||
)) never();
|
)) never();
|
||||||
let fun = funs[action];
|
|
||||||
|
|
||||||
if (action !== "fmt") {
|
if (action !== "fmt") {
|
||||||
INPUT = OUTPUT;
|
INPUT = OUTPUT;
|
||||||
|
@ -133,7 +133,7 @@ function packPosts(posts, view) {
|
||||||
* @return {Uint8Array} */
|
* @return {Uint8Array} */
|
||||||
function bufSlice(mem, ptr, len) {
|
function bufSlice(mem, ptr, len) {
|
||||||
return new Uint8Array(mem.buffer, ptr.value,
|
return new Uint8Array(mem.buffer, ptr.value,
|
||||||
new DataView(mem.buffer).getUint32(len.value, true));
|
new DataView(mem.buffer).getUint32(len.value, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {WebAssembly.Memory} mem
|
/** @param {WebAssembly.Memory} mem
|
||||||
|
@ -283,27 +283,27 @@ async function bindCodeEdit(target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {{ Array<string> }}
|
* @type {Array<string>}
|
||||||
* to be synched with `enum TokenGroup` in bytecode/src/fmt.rs */
|
* to be synched with `enum TokenGroup` in bytecode/src/fmt.rs */
|
||||||
const TOK_CLASSES = [
|
const TOK_CLASSES = [
|
||||||
'Blank',
|
'Blank',
|
||||||
'Comment',
|
'Comment',
|
||||||
'Keyword',
|
'Keyword',
|
||||||
'Identifier',
|
'Identifier',
|
||||||
'Directive',
|
'Directive',
|
||||||
'Number',
|
'Number',
|
||||||
'String',
|
'String',
|
||||||
'Op',
|
'Op',
|
||||||
'Assign',
|
'Assign',
|
||||||
'Paren',
|
'Paren',
|
||||||
'Bracket',
|
'Bracket',
|
||||||
'Colon',
|
'Colon',
|
||||||
'Comma',
|
'Comma',
|
||||||
'Dot',
|
'Dot',
|
||||||
'Ctor',
|
'Ctor',
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @type {{ [key: string]: (el: HTMLElement) => undefined | Promise<undefined> }} */
|
/** @type {{ [key: string]: (el: HTMLElement) => void | Promise<void> }} */
|
||||||
const applyFns = {
|
const applyFns = {
|
||||||
timestamp: (el) => {
|
timestamp: (el) => {
|
||||||
const timestamp = el.innerText;
|
const timestamp = el.innerText;
|
||||||
|
@ -314,15 +314,16 @@ const applyFns = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {HTMLElement} target
|
* @param {HTMLElement} target */
|
||||||
* @param {string} code */
|
|
||||||
async function fmt(target) {
|
async function fmt(target) {
|
||||||
const code = target.innerText;
|
const code = target.innerText;
|
||||||
const instance = await getFmtInstance();
|
const instance = await getFmtInstance();
|
||||||
const decoder = new TextDecoder('utf-8');
|
const decoder = new TextDecoder('utf-8');
|
||||||
const fmt = modifyCode(instance, code, 'fmt');
|
const fmt = modifyCode(instance, code, 'fmt');
|
||||||
const codeBytes = new TextEncoder('utf-8').encode(fmt);
|
if (typeof fmt !== "string") never()
|
||||||
|
const codeBytes = new TextEncoder().encode(fmt);
|
||||||
const tok = modifyCode(instance, fmt, 'tok');
|
const tok = modifyCode(instance, fmt, 'tok');
|
||||||
|
if (!(tok instanceof Uint8Array)) never();
|
||||||
target.innerHTML = '';
|
target.innerHTML = '';
|
||||||
let start = 0;
|
let start = 0;
|
||||||
let kind = tok[0];
|
let kind = tok[0];
|
||||||
|
@ -429,6 +430,7 @@ if (window.location.hostname === 'localhost') {
|
||||||
const code = "main:=fn():void{return}";
|
const code = "main:=fn():void{return}";
|
||||||
const inst = await getFmtInstance()
|
const inst = await getFmtInstance()
|
||||||
const fmtd = modifyCode(inst, code, "fmt") ?? never();
|
const fmtd = modifyCode(inst, code, "fmt") ?? never();
|
||||||
|
if (typeof fmtd !== "string") never();
|
||||||
const prev = modifyCode(inst, fmtd, "minify") ?? never();
|
const prev = modifyCode(inst, fmtd, "minify") ?? never();
|
||||||
if (code != prev) console.error(code, prev);
|
if (code != prev) console.error(code, prev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ async fn amain() {
|
||||||
.route("/profile", get(Profile::page))
|
.route("/profile", get(Profile::page))
|
||||||
.route("/profile-view", get(Profile::get))
|
.route("/profile-view", get(Profile::get))
|
||||||
.route("/profile/:name", get(Profile::get_other_page))
|
.route("/profile/:name", get(Profile::get_other_page))
|
||||||
|
.route("/profile/password", post(PasswordChange::post))
|
||||||
.route("/profile-view/:name", get(Profile::get_other))
|
.route("/profile-view/:name", get(Profile::get_other))
|
||||||
.route("/post", get(Post::page))
|
.route("/post", get(Post::page))
|
||||||
.route("/post-view", get(Post::get))
|
.route("/post-view", get(Post::get))
|
||||||
|
@ -339,6 +340,70 @@ impl fmt::Display for Post {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
struct PasswordChange {
|
||||||
|
old_password: String,
|
||||||
|
new_password: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
error: Option<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PasswordChange {
|
||||||
|
async fn post(
|
||||||
|
session: Session,
|
||||||
|
axum::Form(mut change): axum::Form<PasswordChange>,
|
||||||
|
) -> Html<String> {
|
||||||
|
db::with(|que| {
|
||||||
|
match que.authenticate.query_row((&session.name,), |r| r.get::<_, String>(1)) {
|
||||||
|
Ok(hash) if verify_password(&hash, &change.old_password).is_err() => {
|
||||||
|
change.error = Some("invalid credentials");
|
||||||
|
}
|
||||||
|
Ok(_) => {
|
||||||
|
let new_hashed = hash_password(&change.new_password);
|
||||||
|
match que
|
||||||
|
.change_passowrd
|
||||||
|
.execute((new_hashed, &session.name))
|
||||||
|
.log("execute update")
|
||||||
|
{
|
||||||
|
None => change.error = Some("intenal server error"),
|
||||||
|
Some(0) => change.error = Some("password is incorrect"),
|
||||||
|
Some(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(rusqlite::Error::QueryReturnedNoRows) => {
|
||||||
|
change.error = Some("invalid credentials");
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("login queri failed: {e}");
|
||||||
|
change.error = Some("internal server error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if change.error.is_some() {
|
||||||
|
change.render(&session)
|
||||||
|
} else {
|
||||||
|
PasswordChange::default().render(&session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Page for PasswordChange {
|
||||||
|
fn render_to_buf(self, _: &Session, buf: &mut String) {
|
||||||
|
let Self { old_password, new_password, error } = self;
|
||||||
|
write_html! { (buf)
|
||||||
|
<form "hx-post"="/profile/password" "hx-swap"="outerHTML">
|
||||||
|
if let Some(e) = error { <div class="error">e</div> }
|
||||||
|
<input name="old_password" type="password" autocomplete="old-password"
|
||||||
|
placeholder="old password" value=old_password>
|
||||||
|
<input name="new_password" type="password" autocomplete="new-password" placeholder="new password"
|
||||||
|
value=new_password>
|
||||||
|
<input type="submit" value="submit">
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Profile {
|
struct Profile {
|
||||||
other: Option<String>,
|
other: Option<String>,
|
||||||
|
@ -357,14 +422,19 @@ impl Profile {
|
||||||
impl Page for Profile {
|
impl Page for Profile {
|
||||||
fn render_to_buf(self, session: &Session, buf: &mut String) {
|
fn render_to_buf(self, session: &Session, buf: &mut String) {
|
||||||
db::with(|db| {
|
db::with(|db| {
|
||||||
|
let name = self.other.as_ref().unwrap_or(&session.name);
|
||||||
let iter = db
|
let iter = db
|
||||||
.get_user_posts
|
.get_user_posts
|
||||||
.query_map((self.other.as_ref().unwrap_or(&session.name),), Post::from_row)
|
.query_map((name,), Post::from_row)
|
||||||
.log("get user posts query")
|
.log("get user posts query")
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.filter_map(|p| p.log("user post row"));
|
.filter_map(|p| p.log("user post row"));
|
||||||
write_html! { (buf)
|
write_html! { (*buf)
|
||||||
|
if name == &session.name {
|
||||||
|
|b|{PasswordChange::default().render_to_buf(session, b)}
|
||||||
|
}
|
||||||
|
|
||||||
for post in iter {
|
for post in iter {
|
||||||
!{post}
|
!{post}
|
||||||
} else {
|
} else {
|
||||||
|
@ -399,7 +469,7 @@ struct Login {
|
||||||
|
|
||||||
impl PublicPage for Login {
|
impl PublicPage for Login {
|
||||||
fn render_to_buf(self, buf: &mut String) {
|
fn render_to_buf(self, buf: &mut String) {
|
||||||
let Login { name, password, error } = self;
|
let Self { name, password, error } = self;
|
||||||
write_html! { (buf)
|
write_html! { (buf)
|
||||||
<form "hx-post"="/login" "hx-swap"="outerHTML">
|
<form "hx-post"="/login" "hx-swap"="outerHTML">
|
||||||
if let Some(e) = error { <div class="error">e</div> }
|
if let Some(e) = error { <div class="error">e</div> }
|
||||||
|
@ -439,13 +509,12 @@ impl Login {
|
||||||
data.error = Some("invalid credentials");
|
data.error = Some("invalid credentials");
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("foo {e}");
|
log::error!("login queri failed: {e}");
|
||||||
data.error = Some("internal server error");
|
data.error = Some("internal server error");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if data.error.is_some() {
|
if data.error.is_some() {
|
||||||
log::error!("what {:?}", data);
|
|
||||||
Err(data.render())
|
Err(data.render())
|
||||||
} else {
|
} else {
|
||||||
Ok(AppendHeaders([
|
Ok(AppendHeaders([
|
||||||
|
@ -682,6 +751,7 @@ mod db {
|
||||||
gen_queries! {
|
gen_queries! {
|
||||||
pub struct Queries {
|
pub struct Queries {
|
||||||
register: "INSERT INTO user (name, password_hash) VALUES(?, ?)",
|
register: "INSERT INTO user (name, password_hash) VALUES(?, ?)",
|
||||||
|
change_passowrd: "UPDATE user SET password_hash = ? WHERE name = ?",
|
||||||
authenticate: "SELECT name, password_hash FROM user WHERE name = ?",
|
authenticate: "SELECT name, password_hash FROM user WHERE name = ?",
|
||||||
login: "INSERT OR REPLACE INTO session (id, username, expiration) VALUES(?, ?, ?)",
|
login: "INSERT OR REPLACE INTO session (id, username, expiration) VALUES(?, ?, ?)",
|
||||||
logout: "DELETE FROM session WHERE id = ?",
|
logout: "DELETE FROM session WHERE id = ?",
|
||||||
|
|
Loading…
Reference in a new issue