Skip to content

Commit 49f2dae

Browse files
committed
Negate erase option and make optional
This makes it more intuitive for an empty request body to be equivalent to the option being set to false.
1 parent f41743c commit 49f2dae

File tree

2 files changed

+18
-56
lines changed

2 files changed

+18
-56
lines changed

crates/handlers/src/admin/v1/users/deactivate.rs

Lines changed: 15 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,13 @@ impl IntoResponse for RouteError {
5252
}
5353

5454
/// # JSON payload for the `POST /api/admin/v1/users/:id/deactivate` endpoint
55-
#[derive(Deserialize, JsonSchema)]
55+
#[derive(Default, Deserialize, JsonSchema)]
5656
#[serde(rename = "DeactivateUserRequest")]
5757
pub struct Request {
58-
/// Whether the user should be GDPR-erased from the homeserver.
59-
erase: bool,
60-
}
61-
62-
impl Default for Request {
63-
fn default() -> Self {
64-
Self { erase: true }
65-
}
58+
/// Whether to skip requesting the homeserver to GDPR-erase the user upon
59+
/// deactivation.
60+
#[serde(default)]
61+
skip_erase: bool,
6662
}
6763

6864
pub fn doc(mut operation: TransformOperation) -> TransformOperation {
@@ -120,7 +116,7 @@ pub async fn handler(
120116
.schedule_job(
121117
&mut rng,
122118
&clock,
123-
DeactivateUserJob::new(&user, params.erase),
119+
DeactivateUserJob::new(&user, !params.skip_erase),
124120
)
125121
.await?;
126122

@@ -142,7 +138,7 @@ mod tests {
142138

143139
use crate::test_utils::{RequestBuilderExt, ResponseExt, TestState, setup};
144140

145-
async fn test_deactivate_user_helper(pool: PgPool, erase: Option<bool>) {
141+
async fn test_deactivate_user_helper(pool: PgPool, skip_erase: Option<bool>) {
146142
setup();
147143
let mut state = TestState::from_pool(pool.clone()).await.unwrap();
148144
let token = state.token_with_scope("urn:mas:admin").await;
@@ -157,10 +153,10 @@ mod tests {
157153

158154
let request =
159155
Request::post(format!("/api/admin/v1/users/{}/deactivate", user.id)).bearer(&token);
160-
let request = match erase {
156+
let request = match skip_erase {
161157
None => request.empty(),
162-
Some(erase) => request.json(serde_json::json!({
163-
"erase": erase,
158+
Some(skip_erase) => request.json(serde_json::json!({
159+
"skip_erase": skip_erase,
164160
})),
165161
};
166162
let response = state.request(request).await;
@@ -182,7 +178,10 @@ mod tests {
182178
.await
183179
.expect("Deactivation job to be scheduled");
184180
assert_eq!(job["user_id"], serde_json::json!(user.id));
185-
assert_eq!(job["hs_erase"], serde_json::json!(erase.unwrap_or(true)));
181+
assert_eq!(
182+
job["hs_erase"],
183+
serde_json::json!(!skip_erase.unwrap_or(false))
184+
);
186185

187186
// Make sure to run the jobs in the queue
188187
state.run_jobs_in_queue().await;
@@ -223,45 +222,10 @@ mod tests {
223222
}
224223

225224
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
226-
async fn test_deactivate_user_with_explicit_erase(pool: PgPool) {
225+
async fn test_deactivate_user_skip_erase(pool: PgPool) {
227226
test_deactivate_user_helper(pool, Option::Some(true)).await;
228227
}
229228

230-
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
231-
async fn test_deactivate_user_without_erase(pool: PgPool) {
232-
test_deactivate_user_helper(pool, Option::Some(false)).await;
233-
}
234-
235-
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
236-
async fn test_deactivate_user_missing_erase(pool: PgPool) {
237-
setup();
238-
let mut state = TestState::from_pool(pool.clone()).await.unwrap();
239-
let token = state.token_with_scope("urn:mas:admin").await;
240-
241-
let mut repo = state.repository().await.unwrap();
242-
let user = repo
243-
.user()
244-
.add(&mut state.rng(), &state.clock, "alice".to_owned())
245-
.await
246-
.unwrap();
247-
repo.save().await.unwrap();
248-
249-
let request = Request::post(format!("/api/admin/v1/users/{}/deactivate", user.id))
250-
.bearer(&token)
251-
.json(serde_json::json!({}));
252-
let response = state.request(request).await;
253-
response.assert_status(StatusCode::UNPROCESSABLE_ENTITY);
254-
255-
// It should have not scheduled a deactivation job for the user
256-
let count: i64 = sqlx::query_scalar(
257-
"SELECT COUNT(1) FROM queue_jobs WHERE queue_name = 'deactivate-user'",
258-
)
259-
.fetch_one(&pool)
260-
.await
261-
.unwrap();
262-
assert_eq!(count, 0);
263-
}
264-
265229
#[sqlx::test(migrator = "mas_storage_pg::MIGRATOR")]
266230
async fn test_deactivate_locked_user(pool: PgPool) {
267231
setup();

docs/api/spec.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3884,12 +3884,10 @@
38843884
"DeactivateUserRequest": {
38853885
"title": "JSON payload for the `POST /api/admin/v1/users/:id/deactivate` endpoint",
38863886
"type": "object",
3887-
"required": [
3888-
"erase"
3889-
],
38903887
"properties": {
3891-
"erase": {
3892-
"description": "Whether the user should be GDPR-erased from the homeserver.",
3888+
"skip_erase": {
3889+
"description": "Whether to skip requesting the homeserver to GDPR-erase the user upon deactivation.",
3890+
"default": false,
38933891
"type": "boolean"
38943892
}
38953893
}

0 commit comments

Comments
 (0)