Added QoL error handling

This commit is contained in:
xeovalyte 2024-10-04 17:00:09 +02:00
parent a53ad775dc
commit 2bca9bba60
Signed by: xeovalyte
SSH Key Fingerprint: SHA256:kSQDrQDmKzljJzfGYcd3m9RqHi4h8rSwkZ3sQ9kBURo
4 changed files with 56 additions and 31 deletions

View File

@ -318,7 +318,7 @@ async fn relate_member(registration_token: String) -> Result<(), ServerFnError>
let user = Session::fetch_current_user().await?;
let member_id = Member::fetch_from_registration_token(registration_token).await?;
user.relate_member(member_id.id).await?;
user.relate_member(&member_id.id).await?;
Ok(())
}
@ -326,6 +326,6 @@ async fn relate_member(registration_token: String) -> Result<(), ServerFnError>
async fn delete_member_relation(member_id: String) -> Result<(), ServerFnError> {
let user = Session::fetch_current_user().await?;
user.remove_relation(member_id).await?;
user.remove_relation(&member_id).await?;
Ok(())
}

View File

@ -34,6 +34,8 @@ impl Member {
pub async fn fetch_all() -> Result<Vec<Self>, surrealdb::Error> {
let mut res = DB.query("SELECT id, name.first, name.full, hours, groups, diploma, registration_token FROM member").await?;
res = res.check()?;
let members: Vec<Self> = res.take(0)?;
Ok(members)
@ -47,6 +49,8 @@ impl Member {
.bind(("registration_token", registration_token))
.await?;
res = res.check()?;
match res.take(0)? {
Some(m) => Ok(m),
None => Err(crate::Error::NoDocument),
@ -61,6 +65,8 @@ impl Member {
.bind(("user_id", user_id))
.await?;
res = res.check()?;
let members: Vec<Self> = res.take(0)?;
Ok(members)

View File

@ -24,6 +24,8 @@ impl Session {
.bind(("user_id", user_id))
.await?;
res = res.check()?;
let session: Option<Self> = res.take(0)?;
match session {
@ -67,6 +69,8 @@ impl Session {
.bind(("session_token", session_token))
.await?;
res = res.check()?;
let user: Option<User> = res.take(0)?;
match user {
@ -111,10 +115,13 @@ impl Session {
}
pub async fn delete_session(user_id: String) -> Result<(), crate::Error> {
DB.query("DELETE ONLY session WHERE user = type::thing('user', $user_id)")
let res = DB
.query("DELETE ONLY session WHERE user = type::thing('user', $user_id)")
.bind(("user_id", user_id))
.await?;
res.check()?;
Ok(())
}

View File

@ -3,7 +3,10 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "server")]
use crate::util::surrealdb::{thing_to_string, DB};
#[cfg(feature = "server")]
use surrealdb::sql::statements::{BeginStatement, CommitStatement};
use surrealdb::sql::{
statements::{BeginStatement, CommitStatement},
Thing,
};
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
pub struct User {
@ -37,6 +40,8 @@ impl User {
.query(CommitStatement::default())
.await?;
res = res.check()?;
let user: Option<Self> = res.take(0)?;
match user {
@ -45,36 +50,40 @@ impl User {
}
}
pub async fn relate_member(&self, member_id: String) -> Result<(), crate::Error> {
let mut res = DB
pub async fn relate_member(&self, member_id: &str) -> Result<(), crate::Error> {
let res = DB
.query("
IF (SELECT * FROM ONLY user_to_member WHERE in = type::thing('user', $user_id) AND out = type::thing('member', $member_id) LIMIT 1) == NONE {
RELATE ONLY (type::thing('user', $user_id))->user_to_member->(type::thing('member', $member_id));
IF (SELECT id FROM ONLY user_to_member WHERE in = $user AND out = $member LIMIT 1) == NONE {
RELATE ONLY $user->user_to_member->$member;
} ELSE {
THROW 'Relation already exists'
};
")
.bind(("user_id", self.id.to_string()))
.bind(("member_id", member_id))
.bind(("user", Thing::from(("user", self.id.as_str()))))
.bind(("member", Thing::from(("member", member_id))))
.await?;
if res.take_errors().len() != 0 {
return Err(crate::Error::NoDocument);
}
res.check()?;
Ok(())
}
pub async fn remove_relation(&self, member_id: String) -> Result<(), crate::Error> {
let mut res = DB
.query("DELETE type::thing('user', $user_id)->user_to_member WHERE out = type::thing('member', $member_id)")
.bind(("user_id", self.id.clone()))
.bind(("member_id", member_id))
pub async fn remove_relation(&self, member_id: &str) -> Result<(), crate::Error> {
let res = DB
.query(
"
IF (SELECT count() FROM user_to_member WHERE in = $user GROUP ALL)[0].count == 1 {
THROW 'At least one relation is required'
} ELSE {
DELETE $user->user_to_member WHERE out = $member
};
",
)
.bind(("user", Thing::from(("user", self.id.as_str()))))
.bind(("member", Thing::from(("member", member_id))))
.await?;
if res.take_errors().len() != 0 {
return Err(crate::Error::NoDocument);
}
res.check()?;
Ok(())
}
@ -85,9 +94,12 @@ impl User {
) -> Result<String, crate::Error> {
let mut res = DB
.query("SELECT VALUE id FROM user WHERE email = $email AND crypto::argon2::compare(password, $password)")
.bind(("email", email)).bind(("password", password))
.bind(("email", email))
.bind(("password", password))
.await?;
res = res.check()?;
let id: Option<String> = res.take(0)?;
match id {
@ -98,11 +110,13 @@ impl User {
pub async fn change_email(&self, new_email: String) -> Result<String, crate::Error> {
let mut res = DB
.query("UPDATE type::thing('user', $user_id) SET email = $email RETURN VALUE email")
.bind(("user_id", self.id.to_string()))
.query("UPDATE $user SET email = $email RETURN VALUE email")
.bind(("user", Thing::from(("user", self.id.as_str()))))
.bind(("email", new_email))
.await?;
res = res.check()?;
let email: Option<String> = res.take(0)?;
match email {
@ -116,26 +130,24 @@ impl User {
old_password: String,
new_password: String,
) -> Result<(), crate::Error> {
let mut res = DB
let res = DB
.query(
"
LET $user = (SELECT * FROM ONLY type::thing('user', $user_id));
LET $user = (SELECT * FROM ONLY $user);
IF crypto::argon2::compare($user.password, $old_password) {
UPDATE type::thing('user', $user_id) SET password = crypto::argon2::generate($new_password)
UPDATE $user SET password = crypto::argon2::generate($new_password)
} ELSE {
THROW 'Password dit not match'
};
",
)
.bind(("user_id", self.id.to_string()))
.bind(("user", Thing::from(("user", self.id.as_str()))))
.bind(("old_password", old_password))
.bind(("new_password", new_password))
.await?;
if res.take_errors().len() != 0 {
return Err(crate::Error::NoDocument);
}
res.check()?;
Ok(())
}