diff --git a/src/components/settings.rs b/src/components/settings.rs index 4948ef9..3f176c9 100644 --- a/src/components/settings.rs +++ b/src/components/settings.rs @@ -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(()) } diff --git a/src/util/model/member.rs b/src/util/model/member.rs index 1bdb279..7731c31 100644 --- a/src/util/model/member.rs +++ b/src/util/model/member.rs @@ -34,6 +34,8 @@ impl Member { pub async fn fetch_all() -> Result, 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 = 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 = res.take(0)?; Ok(members) diff --git a/src/util/model/session.rs b/src/util/model/session.rs index daf0481..385245e 100644 --- a/src/util/model/session.rs +++ b/src/util/model/session.rs @@ -24,6 +24,8 @@ impl Session { .bind(("user_id", user_id)) .await?; + res = res.check()?; + let session: Option = res.take(0)?; match session { @@ -67,6 +69,8 @@ impl Session { .bind(("session_token", session_token)) .await?; + res = res.check()?; + let user: Option = 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(()) } diff --git a/src/util/model/user.rs b/src/util/model/user.rs index debb998..fdd012d 100644 --- a/src/util/model/user.rs +++ b/src/util/model/user.rs @@ -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 = 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 { 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 = res.take(0)?; match id { @@ -98,11 +110,13 @@ impl User { pub async fn change_email(&self, new_email: String) -> Result { 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 = 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(()) }