Skip to content

Commit 861d93d

Browse files
committed
backend: add delete_user route
1 parent 53e0533 commit 861d93d

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed

backend/src/routes/user/delete.rs

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
use actix_web::{delete, web, HttpResponse, Responder};
2+
use db_connector::models::{allowed_users::AllowedUser, chargers::Charger};
3+
use diesel::{prelude::*, result::Error::NotFound};
4+
use serde::{Deserialize, Serialize};
5+
use utoipa::ToSchema;
6+
7+
use crate::{error::Error, routes::{auth::login::{validate_password, FindBy}, charger::remove::{delete_all_allowed_users, delete_all_keys, delete_charger}, user::logout::delete_all_refresh_tokens}, utils::{get_connection, web_block_unpacked}, AppState};
8+
9+
#[derive(ToSchema, Serialize, Deserialize)]
10+
pub struct DeleteSchema {
11+
#[schema(value_type = Vec<u32>)]
12+
pub login_key: Vec<u8>
13+
}
14+
15+
async fn get_all_chargers_for_user(user_id: uuid::Uuid, state: &web::Data<AppState>) -> actix_web::Result<Vec<Charger>> {
16+
let mut conn = get_connection(state)?;
17+
let allowed_users: Vec<AllowedUser> = web_block_unpacked(move || {
18+
use db_connector::schema::allowed_users::dsl as allowed_users;
19+
20+
match allowed_users::allowed_users.filter(allowed_users::user_id.eq(user_id)).select(AllowedUser::as_select()).load(&mut conn) {
21+
Ok(v) => Ok(v),
22+
Err(NotFound) => Ok(Vec::new()),
23+
Err(_err) => Err(Error::InternalError),
24+
}
25+
}).await?;
26+
27+
let charger_ids: Vec<i32> = allowed_users.into_iter().map(|u| u.charger_id).collect();
28+
let mut conn = get_connection(state)?;
29+
web_block_unpacked(move || {
30+
use db_connector::schema::chargers::dsl::*;
31+
32+
match chargers.filter(id.eq_any(charger_ids)).select(Charger::as_select()).load(&mut conn) {
33+
Ok(v) => Ok(v),
34+
Err(NotFound) => Ok(Vec::new()),
35+
Err(_err) => Err(Error::InternalError),
36+
}
37+
}).await
38+
}
39+
40+
#[delete("/delete")]
41+
pub async fn delete_user(state: web::Data<AppState>, user_id: crate::models::uuid::Uuid, payload: web::Json<DeleteSchema>) -> actix_web::Result<impl Responder> {
42+
let user_id = user_id.into();
43+
44+
let conn = get_connection(&state)?;
45+
let _ = validate_password(&payload.login_key, FindBy::Uuid(user_id), conn).await?;
46+
47+
let chargers = get_all_chargers_for_user(user_id, &state).await?;
48+
let charger_ids: Vec<i32> = chargers.into_iter().map(|c| c.id).collect();
49+
for id in charger_ids.into_iter() {
50+
delete_all_keys(id, &state).await?;
51+
delete_all_allowed_users(id, &state).await?;
52+
delete_charger(id, &state).await?;
53+
}
54+
55+
delete_all_refresh_tokens(user_id, &state).await?;
56+
let mut conn = get_connection(&state)?;
57+
web_block_unpacked(move || {
58+
use db_connector::schema::users::dsl::*;
59+
60+
match diesel::delete(users.find(user_id)).execute(&mut conn) {
61+
Ok(_) => Ok(()),
62+
Err(_err) => {
63+
println!("err: {:?}", _err);
64+
Err(Error::InternalError)
65+
},
66+
}
67+
}).await?;
68+
69+
Ok(HttpResponse::Ok())
70+
}
71+
72+
#[cfg(test)]
73+
mod tests {
74+
use actix_web::{cookie::Cookie, test, App};
75+
use db_connector::{models::{allowed_users::AllowedUser, chargers::Charger, users::User, wg_keys::WgKey}, test_connection_pool};
76+
use diesel::{prelude::*, result::Error::NotFound};
77+
78+
use crate::{middleware::jwt::JwtMiddleware, routes::{auth::get_login_salt::tests::get_test_login_salt, user::tests::{get_test_uuid, hash_test_key, TestUser}}, tests::configure, utils::generate_random_bytes};
79+
80+
use super::{delete_user, DeleteSchema};
81+
82+
83+
//TODO: add test for shared charger once it is merged
84+
#[actix_web::test]
85+
async fn test_delete() {
86+
let (mut user1, user1_mail) = TestUser::random().await;
87+
let (mut user2, user2_mail) = TestUser::random().await;
88+
let token = user1.login().await.to_owned();
89+
user2.login().await;
90+
let charger = user1.add_random_charger().await;
91+
let charger2 = user2.add_random_charger().await;
92+
let uid1 = get_test_uuid(&user1_mail).unwrap();
93+
let uid2 = get_test_uuid(&user2_mail).unwrap();
94+
95+
let app = App::new()
96+
.configure(configure)
97+
.wrap(JwtMiddleware)
98+
.service(delete_user);
99+
let app = test::init_service(app).await;
100+
101+
let login_salt = get_test_login_salt(&user1_mail).await;
102+
let login_key = hash_test_key(&user1.password, &login_salt, None);
103+
let schema = DeleteSchema {
104+
login_key
105+
};
106+
let req = test::TestRequest::delete()
107+
.uri("/delete")
108+
.cookie(Cookie::new("access_token", token))
109+
.set_json(schema)
110+
.to_request();
111+
112+
let resp = test::call_service(&app, req).await;
113+
assert_eq!(resp.status(), 200);
114+
115+
let pool = test_connection_pool();
116+
let mut conn = pool.get().unwrap();
117+
118+
{
119+
use db_connector::schema::allowed_users::dsl::*;
120+
121+
let res = allowed_users.filter(user_id.eq(uid1)).select(AllowedUser::as_select()).get_result(&mut conn);
122+
assert_eq!(res, Err(NotFound));
123+
124+
let res = allowed_users.filter(user_id.eq(uid2)).select(AllowedUser::as_select()).get_result(&mut conn);
125+
assert!(res.is_ok());
126+
}
127+
{
128+
use db_connector::schema::chargers::dsl::*;
129+
130+
let res = chargers.filter(id.eq(charger.0)).select(Charger::as_select()).get_result(&mut conn);
131+
assert_eq!(res, Err(NotFound));
132+
133+
let res = chargers.filter(id.eq(charger2.0)).select(Charger::as_select()).get_result(&mut conn);
134+
assert!(res.is_ok());
135+
}
136+
{
137+
use db_connector::schema::wg_keys::dsl::*;
138+
139+
let res = wg_keys.filter(charger_id.eq(charger.0)).select(WgKey::as_select()).get_result(&mut conn);
140+
assert_eq!(res, Err(NotFound));
141+
142+
let res = wg_keys.filter(charger_id.eq(charger2.0)).select(WgKey::as_select()).get_result(&mut conn);
143+
assert!(res.is_ok());
144+
}
145+
{
146+
use db_connector::schema::users::dsl::*;
147+
148+
let res = users.find(uid1).select(User::as_select()).get_result(&mut conn);
149+
assert_eq!(res, Err(NotFound));
150+
151+
let res = users.find(uid2).select(User::as_select()).get_result(&mut conn);
152+
assert!(res.is_ok());
153+
}
154+
}
155+
156+
#[actix_web::test]
157+
async fn test_delete_wrong_password() {
158+
let (mut user1, user1_mail) = TestUser::random().await;
159+
let (mut user2, user2_mail) = TestUser::random().await;
160+
let token = user1.login().await.to_owned();
161+
user2.login().await;
162+
let charger = user1.add_random_charger().await;
163+
let charger2 = user2.add_random_charger().await;
164+
let uid1 = get_test_uuid(&user1_mail).unwrap();
165+
let uid2 = get_test_uuid(&user2_mail).unwrap();
166+
167+
let app = App::new()
168+
.configure(configure)
169+
.wrap(JwtMiddleware)
170+
.service(delete_user);
171+
let app = test::init_service(app).await;
172+
173+
let schema = DeleteSchema {
174+
login_key: generate_random_bytes()
175+
};
176+
let req = test::TestRequest::delete()
177+
.uri("/delete")
178+
.cookie(Cookie::new("access_token", token))
179+
.set_json(schema)
180+
.to_request();
181+
182+
let resp = test::call_service(&app, req).await;
183+
assert_eq!(resp.status(), 400);
184+
185+
let pool = test_connection_pool();
186+
let mut conn = pool.get().unwrap();
187+
188+
{
189+
use db_connector::schema::allowed_users::dsl::*;
190+
191+
let res = allowed_users.filter(user_id.eq(uid1)).select(AllowedUser::as_select()).get_result(&mut conn);
192+
assert!(res.is_ok());
193+
194+
let res = allowed_users.filter(user_id.eq(uid2)).select(AllowedUser::as_select()).get_result(&mut conn);
195+
assert!(res.is_ok());
196+
}
197+
{
198+
use db_connector::schema::chargers::dsl::*;
199+
200+
let res = chargers.filter(id.eq(charger.0)).select(Charger::as_select()).get_result(&mut conn);
201+
assert!(res.is_ok());
202+
203+
let res = chargers.filter(id.eq(charger2.0)).select(Charger::as_select()).get_result(&mut conn);
204+
assert!(res.is_ok());
205+
}
206+
{
207+
use db_connector::schema::wg_keys::dsl::*;
208+
209+
let res = wg_keys.filter(charger_id.eq(charger.0)).select(WgKey::as_select()).get_result(&mut conn);
210+
assert!(res.is_ok());
211+
212+
let res = wg_keys.filter(charger_id.eq(charger2.0)).select(WgKey::as_select()).get_result(&mut conn);
213+
assert!(res.is_ok());
214+
}
215+
{
216+
use db_connector::schema::users::dsl::*;
217+
218+
let res = users.find(uid1).select(User::as_select()).get_result(&mut conn);
219+
assert!(res.is_ok());
220+
221+
let res = users.find(uid2).select(User::as_select()).get_result(&mut conn);
222+
assert!(res.is_ok());
223+
}
224+
}
225+
}

0 commit comments

Comments
 (0)