1use scripting::runtime::{alloc_string_ref, read_string_arg};
13use server::command::CmdResult;
14use server::command::user::VerifyUserPassword;
15use wasmtime::{ArrayRef, Caller, Linker, Rooted};
16
17use crate::session::SessionData;
18
19pub const REGISTERED_COMMANDS: &[&str] = &["verify-user-password"];
20
21pub fn register(linker: &mut Linker<SessionData>) -> wasmtime::Result<()> {
22 linker.func_wrap_async(
23 "nomi",
24 "user_verify_user_password",
25 |mut caller: Caller<'_, SessionData>,
26 (email_arg, password_arg): (Option<Rooted<ArrayRef>>, Option<Rooted<ArrayRef>>)|
27 -> Box<
28 dyn std::future::Future<Output = wasmtime::Result<Option<Rooted<ArrayRef>>>> + Send,
29 > {
30 Box::new(async move {
31 let email = read_string_arg(&mut caller, email_arg)?;
32 let password = read_string_arg(&mut caller, password_arg)?;
33 match run_verify_user_password(email, password).await? {
34 Some(id) => Ok(Some(alloc_string_ref(&mut caller, id.as_bytes())?)),
35 None => Ok(None),
36 }
37 })
38 },
39 )?;
40 Ok(())
41}
42
43async fn run_verify_user_password(
48 email_arg: Option<String>,
49 password_arg: Option<String>,
50) -> wasmtime::Result<Option<String>> {
51 let email = email_arg
52 .filter(|s| !s.is_empty())
53 .ok_or_else(|| wasmtime::Error::msg("verify-user-password: missing or empty :email arg"))?;
54 let password = password_arg
55 .ok_or_else(|| wasmtime::Error::msg("verify-user-password: missing :password arg"))?;
56 match VerifyUserPassword::new()
57 .email(email)
58 .password(password)
59 .run()
60 .await
61 {
62 Ok(Some(CmdResult::Uuid(id))) => Ok(Some(id.to_string())),
63 Ok(Some(CmdResult::Bool(false))) | Ok(None) => Ok(None),
64 Ok(Some(other)) => Err(wasmtime::Error::msg(format!(
65 "verify-user-password: unexpected variant {other:?}"
66 ))),
67 Err(err) => Err(wasmtime::Error::msg(format!("verify-user-password: {err}"))),
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[tokio::test]
76 async fn run_verify_user_password_missing_email_emits_error() {
77 let err = run_verify_user_password(None, Some("pw".into()))
78 .await
79 .unwrap_err();
80 assert!(err.to_string().contains(":email"), "got: {err}");
81 }
82
83 #[tokio::test]
84 async fn run_verify_user_password_empty_email_emits_error() {
85 let err = run_verify_user_password(Some(String::new()), Some("pw".into()))
86 .await
87 .unwrap_err();
88 assert!(err.to_string().contains(":email"), "got: {err}");
89 }
90
91 #[tokio::test]
92 async fn run_verify_user_password_missing_password_emits_error() {
93 let err = run_verify_user_password(Some("u@example.com".into()), None)
94 .await
95 .unwrap_err();
96 assert!(err.to_string().contains(":password"), "got: {err}");
97 }
98}