From 1b0e5d53c2b3c3ee232f91319b22929e1a690d6c Mon Sep 17 00:00:00 2001 From: L-Nafaryus Date: Sat, 23 Mar 2024 00:13:01 +0500 Subject: [PATCH] backend: remove user api --- crates/frontend/src/components/Login.vue | 2 +- crates/frontend/src/views/Me.vue | 9 ++++--- crates/frontend/src/views/NotFound.vue | 0 src/api/v1/errors.rs | 2 ++ src/api/v1/mod.rs | 1 + src/api/v1/user.rs | 30 +++++++++++++++++++++++- src/db/user.rs | 21 +++++++++++++---- 7 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 crates/frontend/src/views/NotFound.vue diff --git a/crates/frontend/src/components/Login.vue b/crates/frontend/src/components/Login.vue index 994d354..bfe7014 100644 --- a/crates/frontend/src/components/Login.vue +++ b/crates/frontend/src/components/Login.vue @@ -7,7 +7,7 @@ const password = defineModel("password"); const errorMessage = ref(null); async function login() { - await fetch(import.meta.hot ? "http://localhost:54600/api/v1/login_user" : "/api/v1/login_user", { + await fetch(import.meta.hot ? "http://localhost:54600/api/v1/user/login" : "/api/v1/user/login", { method: "POST", headers: { "Content-Type": "application/json", diff --git a/crates/frontend/src/views/Me.vue b/crates/frontend/src/views/Me.vue index d28a45a..ef8d6dd 100644 --- a/crates/frontend/src/views/Me.vue +++ b/crates/frontend/src/views/Me.vue @@ -9,13 +9,12 @@ const is_admin = ref(null); const errorMessage = ref(null); onMounted(async () => { - const asd = await fetch(import.meta.hot ? "http://localhost:54600/api/v1/me" : "/api/v1/me", { + const asd = await fetch(import.meta.hot ? "http://localhost:54600/api/v1/user/profile" : "/api/v1/user/profile", { method: "GET", headers: { "Content-Type": "application/json", }, credentials: "include", - mode: "cors", }) .then(async response => { const isJson = response.headers.get('content-type')?.includes('application/json'); @@ -26,9 +25,9 @@ onMounted(async () => { return Promise.reject(error); } - name.value = data.data.user.name; - email.value = data.data.user.email; - is_admin.value = data.data.user.is_admin; + name.value = data.user.name; + email.value = data.user.email; + is_admin.value = data.user.is_admin; }) .catch(error => { errorMessage.value = error; diff --git a/crates/frontend/src/views/NotFound.vue b/crates/frontend/src/views/NotFound.vue new file mode 100644 index 0000000..e69de29 diff --git a/src/api/v1/errors.rs b/src/api/v1/errors.rs index daf9413..bc90e36 100644 --- a/src/api/v1/errors.rs +++ b/src/api/v1/errors.rs @@ -4,6 +4,7 @@ use serde_json::json; #[derive(Debug)] pub enum AuthError { InternalError(E), + InternalE, MissingCredentials, InvalidCredentials, MissingToken, @@ -15,6 +16,7 @@ impl IntoResponse for AuthError { fn into_response(self) -> axum::response::Response { let (status, message) = match self { Self::InternalError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + Self::InternalE => (StatusCode::INTERNAL_SERVER_ERROR, "Internal E".to_string()), Self::MissingCredentials => { (StatusCode::BAD_REQUEST, "Missing credentials".to_string()) } diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index 135f28c..5324f82 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -31,6 +31,7 @@ pub fn routes(state: Arc) -> Router { Router::new() .route("/v1/healthcheck", get(healthcheck)) .route("/v1/user/register", post(user::register)) + .route("/v1/user/remove", post(user::remove)) .route("/v1/user/login", post(user::login)) .route("/v1/user/logout", get(user::logout)) .route("/v1/user/profile", get(user::profile).route_layer(jwt)) diff --git a/src/api/v1/user.rs b/src/api/v1/user.rs index 5729449..cecf88c 100644 --- a/src/api/v1/user.rs +++ b/src/api/v1/user.rs @@ -34,6 +34,11 @@ pub struct FilteredUser { pub is_admin: bool, } +#[derive(serde::Deserialize)] +pub struct RemoveUser { + pub id: String, +} + impl FilteredUser { pub fn from(user: &User) -> Self { FilteredUser { @@ -67,11 +72,34 @@ pub async fn register( .map_err(AuthError::InternalError)?; Ok(Json(json!({ - "status": "success", + "status": StatusCode::OK.to_string(), "user": FilteredUser::from(&user) }))) } +pub async fn remove( + State(state): State>, + Json(body): Json, +) -> Result> { + let user = User::find( + &state.database, + User::by_id(uuid::Uuid::parse_str(&body.id).map_err(|_| AuthError::InvalidCredentials)?), + ) + .await + .map_err(AuthError::InternalError)?; + + let user = match user { + Some(user) => user, + None => return Err(AuthError::MissingUser), + }; + + User::remove(&state.database, user) + .await + .map_err(|_| AuthError::InternalE)?; + + Ok(Json(json!({"status": StatusCode::OK.to_string()}))) +} + pub async fn login( State(state): State>, Json(body): Json, diff --git a/src/db/user.rs b/src/db/user.rs index 8c04013..39ac15f 100644 --- a/src/db/user.rs +++ b/src/db/user.rs @@ -90,15 +90,15 @@ impl User { pub fn by_email(email: String) -> BoxedQuery<'static> { users::table - .select(User::as_select()) .into_boxed() + .select(User::as_select()) .filter(users::email.eq(email)) } pub fn by_id(id: uuid::Uuid) -> BoxedQuery<'static> { users::table - .select(User::as_select()) .into_boxed() + .select(User::as_select()) .filter(users::id.eq(id)) } @@ -116,6 +116,19 @@ impl User { Ok(user) } - #[allow(unused_variables)] - pub fn remove(pool: Pool, email: String) {} + pub async fn remove( + pool: &Pool, + user: User, + ) -> Result<(), DatabaseError> { + let connection = pool.get().await.map_err(DatabaseError::Connection)?; + connection + .interact(move |connection| { + diesel::delete(users::table.filter(users::id.eq(user.id))).execute(connection) + }) + .await + .map_err(|_| DatabaseError::Interaction)? + .map_err(|_| DatabaseError::Interaction)?; + + Ok(()) + } }