W6W6YBQ6VLEPWLG6GG5VJIJ3LGDISF42HAEC5KV3G5CAMCHIHXAQC use surrealdb::sql::Uuid;use ulid::Ulid;pub fn ulid_to_suuid(ulid: Ulid) -> Uuid {let uuid: uuid::Uuid = ulid.into();uuid.into()}
ulid::Ulid::from_string(&self.id.to_string()).map(|ulid| ulid.timestamp_ms() % 999999).unwrap_or(3033132)
let ulid: Ulid = match Ulid::from_string(&self.id.id.to_raw()) {Ok(ulid) => ulid,Err(_) => return DEFAULT_CODE,};ulid.timestamp_ms() % MAX_CODE
let users: Vec<User> = db.create("user").content(signup).await?;dbg!(&users);assert!(users.len() == 1);let Some(user) = users.into_iter().next() else {
let id = ulid::Ulid::new();let user: Option<User> =db.create(("user", ulid_to_suuid(id))).content::<SignupSafe>(signup.into()).await?;let Some(user) = user else {
#V2DEFINE TABLE user SCHEMAFULL;DEFINE TABLE permission SCHEMAFULL;DEFINE TABLE granted SCHEMAFULL;USE NAMESPACE noteboek;USE DATABASE noteboek;DEFINE TABLE user SCHEMAFULL;DEFINE TABLE permission SCHEMAFULL;DEFINE TABLE granted SCHEMAFULL;/**/qqUSE NAMESPACE noteboek;USE DATABASE noteboek;DEFINE TABLE user SCHEMAFULL;DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is::email($value);DEFINE FIELD username ON TABLE user TYPE string;DEFINE FIELD code ON TABLE user TYPE int DEFAULT rand::int(0, 9999999);DEFINE FIELD password ON TABLE user TYPE string;DEFINE INDEX unique_id ON TABLE user COLUMNS username, code UNIQUE;DEFINE TABLE permission SCHEMAFULL;DEFINE FIELD id ON TABLE permission TYPE string;DEFINE FIELD aspect ON TABLE permission TYPE string;DEFINE TABLE granted SCHEMAFULL;DEFINE FIELD in ON TABLE granted TYPE record<user>;DEFINE FIELD out ON TABLE granted TYPE record<permission>;DEFINE FIELD granted ON TABLE granted TYPE datetime DEFAULT time::now();DEFINE INDEX unique_permissions ON TABLE granted COLUMNS in, out UNIQUE;USE NAMESPACE noteboek;USE DATABASE noteboek;DEFINE TABLE user SCHEMAFULL;DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is::email($value);DEFINE FIELD username ON TABLE user TYPE string;USE NAMESPACE noteboek;USE DATABASE noteboek;DEFINE TABLE user SCHEMAFULL;DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is::email($value);DEFINE FIELD username ON TABLE user TYPE string;DEFINE FIELD code ON TABLE user TYPE int DEFAULT rand::ulid();DEFINE FIELD password ON TABLE user TYPE string;DEFINE INDEX unique_id ON TABLE user COLUMNS username, code UNIQUE;DEFINE TABLE permission SCHEMAFULL;DEFINE FIELD id ON TABLE permission TYPE string;DEFINE FIELD aspect ON TABLE permission TYPE string;DEFINE TABLE granted SCHEMAFULL;DEFINE FIELD in ON TABLE granted TYPE record<user>;DEFINE FIELD out ON TABLE granted TYPE record<permission>;DEFINE FIELD granted ON TABLE granted TYPE datetime DEFAULT time::now();DEFINE INDEX unique_permissions ON TABLE granted COLUMNS in, out UNIQUE;USE NAMESPACE noteboek;USE DATABASE noteboek;DEFINE TABLE user SCHEMAFULL;DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is::email($value);DEFINE FIELD username ON TABLE user TYPE string;DEFINE FIELD id ON TABLE user TYPE string DEFAULT rand::ulid();DEFINE FIELD password ON TABLE user TYPE string;DEFINE INDEX unique_id ON TABLE user COLUMNS username, id UNIQUE;DEFINE TABLE permission SCHEMAFULL;DEFINE FIELD id ON TABLE permission TYPE string;DEFINE FIELD aspect ON TABLE permission TYPE string;DEFINE TABLE granted SCHEMAFULL;DEFINE FIELD in ON TABLE granted TYPE record<user>;DEFINE FIELD out ON TABLE granted TYPE record<permission>;DEFINE FIELD granted ON TABLE granted TYPE datetime DEFAULT time::now();DEFINE INDEX unique_permissions ON TABLE granted COLUMNS in, out UNIQUE;USE NAMESPACE noteboek;USE DATABASE noteboek;DEFINE TABLE user SCHEMAFULL;DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is::email($value);DEFINE FIELD username ON TABLE user TYPE string;DEFINE FIELD id ON TABLE user TYPE string DEFAULT rand::ulid();DEFINE FIELD password ON TABLE user TYPE string;DEFINE INDEX unique_id ON TABLE user COLUMNS username, id UNIQUE;DEFINE TABLE permission SCHEMAFULL;DEFINE FIELD id ON TABLE permission TYPE string;DEFINE FIELD aspect ON TABLE permission TYPE string;DEFINE TABLE granted SCHEMAFULL;DEFINE FIELD in ON TABLE granted TYPE record<user>;DEFINE FIELD out ON TABLE granted TYPE record<permission>;DEFINE FIELD granted ON TABLE granted TYPE datetime DEFAULT time::now();DEFINE INDEX unique_permissions ON TABLE granted COLUMNS in, out UNIQUE;USE NAMESPACE noteboek;USE DATABASE noteboek;DEFINE TABLE user SCHEMAFULL;DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is::email($value);DEFINE FIELD username ON TABLE user TYPE string;DEFINE FIELD id ON TABLE user TYPE string DEFAULT rand::ulid();DEFINE FIELD password ON TABLE user TYPE string;DEFINE INDEX unique_id ON TABLE user COLUMNS username, id UNIQUE;DEFINE TABLE permission SCHEMAFULL;DEFINE FIELD id ON TABLE permission TYPE string;DEFINE FIELD aspect ON TABLE permission TYPE string;DEFINE TABLE granted SCHEMAFULL;DEFINE FIELD in ON TABLE granted TYPE record<user>;DEFINE FIELD out ON TABLE granted TYPE record<permission>;DEFINE FIELD granted ON TABLE granted TYPE datetime DEFAULT time::now();DEFINE INDEX unique_permissions ON TABLE granted COLUMNS in, out UNIQUE;INFO FOR TABLE userDROPDELETE user.code;REMOVE FIELD code ON user;INFO FOR TABLE user
history.txt
async fn create_new_user(signup: &Signup,) -> Result<std::collections::HashMap<String, String>, String> {Ok(gloo_net::http::Request::post("/api/v1/signup").json(signup).map_err(|e| format!("JSON creation error: {e}"))?.send().await.map_err(|e| format!("Send error: {e}"))?.json().await.map_err(|e| format!("JSON read error: {e}"))?)
async fn create_new_user(signup: &Signup) -> Result<gloo_net::http::Response, gloo_net::Error> {Ok(gloo_net::http::Request::post("/api/v1/signup").json(signup)?.send().await?)
let ret = create_new_user(&signup).await;if ret.is_ok() {user_status.refetch()}ret
let resp = create_new_user(&signup).await.map_err(|err| error::ApiError {code: error::ErrorCode::JsSendError,message: err.to_string(),})?;let resp_parsed: Result<(), error::ApiError> = resp.json().await.map_err(|err| {error::ApiError { code: error::ErrorCode::JsReadError, message: err.to_string() }})?;resp_parsed
mview! {[user_status.with(|user| match user {Some(Ok(status)) => match status {UserStatus::Anonymous => "not logged in".to_string(),UserStatus::LoggedIn { username, code } => format!("logged in as {username}#{code}")}.into_view(),Some(Err(e)) =>{let e = format!("{}", e);mview! {div class="text-error bg-slate-500" { [e.clone()] }}.into_view()},None => "Loading...".into_view()})]Form action="/api/v1/login" method="POST" {input type="email" name="email";input type="password" name="password";button type="submit" {"Login"
let login_view = move || {if user_status.with(|user| {user.as_ref().is_some_and(|status| {status.as_ref().is_ok_and(|status| status == &UserStatus::Anonymous)})}) {mview! {Form action="/api/v1/login" method="POST" class="join join-vertical my-2" {label for="email" class="label" {span class="label-text" { "Email" }}input type="email" id="email" name="email" class="input input-bordered w-full max-w-xs";label for="password" class="label" {span class="label-text" { "Password" }}input type="password" id="password" name="password" class="input input-bordered w-full max-w-xs";button type="submit" on:submit={move |_| user_status.refetch()} {"Login"}
h2 { "Signup" }Form action="" method="POST" {input type="username" name="username" prop:value=[username.get()] on:input={move |ev| set_username.set(event_target_value(&ev))};input type="email" name="email" prop:value=[email.get()] on:input={move |ev| set_email.set(event_target_value(&ev))};input type="password" name="password" prop:value=[password.get()] on:input={move |ev| set_password.set(event_target_value(&ev))};button type="submit" on:click={move |ev| {ev.prevent_default();signup.dispatch((username.get(), email.get(), password.get()));}} {"Login"
.into_view()} else {mview! {}.into_view()}};let signup_view = move || {mview! {Form action="" method="POST" {input type="username" name="username" prop:value=[username.get()] on:input={move |ev| set_username.set(event_target_value(&ev))};input type="email" name="email" prop:value=[email.get()] on:input={move |ev| set_email.set(event_target_value(&ev))};input type="password" name="password" prop:value=[password.get()] on:input={move |ev| set_password.set(event_target_value(&ev))};button type="submit" on:click={move |ev| {ev.prevent_default();signup.dispatch((username.get(), email.get(), password.get()));}} {"Register"}
p { f["{:?}", signup.value().get()] }}.into_view()};mview! {div class="text-center" {[user_status.with(|user| match user {Some(Ok(status)) => match status {UserStatus::Anonymous => "not logged in".to_string(),UserStatus::LoggedIn { username, code } => format!("logged in as {username}#{code}")}.into_view(),Some(Err(e)) =>{let e = format!("{}", e);mview! {div class="text-error bg-slate-500" { [e.clone()] }}.into_view()},None => "Loading...".into_view()})]
use core::fmt;use serde::Deserialize;#[derive(Deserialize, Clone, Copy, PartialEq, Eq, Hash, Debug)]#[non_exhaustive]#[serde(rename_all = "kebab-case")]pub(crate) enum ErrorCode {// Frontend specificJsSendError,JsReadError,// BackendInvalidCredentials,}impl fmt::Display for ErrorCode {fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {match self {Self::JsSendError => write!(f, "error sending json"),Self::JsReadError => write!(f, "error reading json"),Self::InvalidCredentials => write!(f, "invalid credentials"),}}}#[derive(Deserialize, Clone, Debug)]pub(crate) struct ApiError {pub(crate) code: ErrorCode,pub(crate) message: String,}impl fmt::Display for ApiError {fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {write!(f, "{}: {}", self.code, self.message)}}