@@ -12,8 +12,6 @@ use mas_storage::{
12
12
BoxRng ,
13
13
queue:: { DeactivateUserJob , QueueJobRepositoryExt as _} ,
14
14
} ;
15
- use schemars:: JsonSchema ;
16
- use serde:: Deserialize ;
17
15
use tracing:: info;
18
16
use ulid:: Ulid ;
19
17
@@ -51,36 +49,21 @@ impl IntoResponse for RouteError {
51
49
}
52
50
}
53
51
54
- /// # JSON payload for the `POST /api/admin/v1/users/:id/deactivate` endpoint
55
- #[ derive( Default , Deserialize , JsonSchema ) ]
56
- #[ serde( rename = "DeactivateUserRequest" ) ]
57
- pub struct Request {
58
- /// Whether to skip locking the user before deactivation.
59
- #[ serde( default ) ]
60
- skip_lock : bool ,
61
- }
62
-
63
- pub fn doc ( mut operation : TransformOperation ) -> TransformOperation {
64
- operation
65
- . inner_mut ( )
66
- . request_body
67
- . as_mut ( )
68
- . unwrap ( )
69
- . as_item_mut ( )
70
- . unwrap ( )
71
- . required = false ;
72
-
52
+ pub fn doc ( operation : TransformOperation ) -> TransformOperation {
73
53
operation
74
54
. id ( "deactivateUser" )
75
55
. summary ( "Deactivate a user" )
76
- . description ( "Calling this endpoint will lock and deactivate the user, preventing them from doing any action.
77
- This invalidates any existing session, and will ask the homeserver to make them leave all rooms." )
56
+ . description (
57
+ "Calling this endpoint will deactivate the user, preventing them from doing any action.
58
+ This invalidates any existing session, and will ask the homeserver to make them leave all rooms." ,
59
+ )
78
60
. tag ( "user" )
79
61
. response_with :: < 200 , Json < SingleResponse < User > > , _ > ( |t| {
80
62
// In the samples, the third user is the one locked
81
63
let [ _alice, _bob, charlie, ..] = User :: samples ( ) ;
82
64
let id = charlie. id ( ) ;
83
- let response = SingleResponse :: new ( charlie, format ! ( "/api/admin/v1/users/{id}/deactivate" ) ) ;
65
+ let response =
66
+ SingleResponse :: new ( charlie, format ! ( "/api/admin/v1/users/{id}/deactivate" ) ) ;
84
67
t. description ( "User was deactivated" ) . example ( response)
85
68
} )
86
69
. response_with :: < 404 , RouteError , _ > ( |t| {
@@ -96,19 +79,15 @@ pub async fn handler(
96
79
} : CallContext ,
97
80
NoApi ( mut rng) : NoApi < BoxRng > ,
98
81
id : UlidPathParam ,
99
- body : Option < Json < Request > > ,
100
82
) -> Result < Json < SingleResponse < User > > , RouteError > {
101
- let Json ( params) = body. unwrap_or_default ( ) ;
102
83
let id = * id;
103
- let mut user = repo
84
+ let user = repo
104
85
. user ( )
105
86
. lookup ( id)
106
87
. await ?
107
88
. ok_or ( RouteError :: NotFound ( id) ) ?;
108
89
109
- if !params. skip_lock && user. locked_at . is_none ( ) {
110
- user = repo. user ( ) . lock ( & clock, user) . await ?;
111
- }
90
+ let user = repo. user ( ) . deactivate ( & clock, user) . await ?;
112
91
113
92
info ! ( %user. id, "Scheduling deactivation of user" ) ;
114
93
repo. queue_job ( )
@@ -127,13 +106,14 @@ pub async fn handler(
127
106
mod tests {
128
107
use chrono:: Duration ;
129
108
use hyper:: { Request , StatusCode } ;
130
- use insta:: { allow_duplicates , assert_json_snapshot} ;
109
+ use insta:: assert_json_snapshot;
131
110
use mas_storage:: { Clock , RepositoryAccess , user:: UserRepository } ;
132
111
use sqlx:: PgPool ;
133
112
134
113
use crate :: test_utils:: { RequestBuilderExt , ResponseExt , TestState , setup} ;
135
114
136
- async fn test_deactivate_user_helper ( pool : PgPool , skip_lock : Option < bool > ) {
115
+ #[ sqlx:: test( migrator = "mas_storage_pg::MIGRATOR" ) ]
116
+ async fn test_deactivate_user ( pool : PgPool ) {
137
117
setup ( ) ;
138
118
let mut state = TestState :: from_pool ( pool. clone ( ) ) . await . unwrap ( ) ;
139
119
let token = state. token_with_scope ( "urn:mas:admin" ) . await ;
@@ -146,27 +126,23 @@ mod tests {
146
126
. unwrap ( ) ;
147
127
repo. save ( ) . await . unwrap ( ) ;
148
128
149
- let request =
150
- Request :: post ( format ! ( "/api/admin/v1/users/{}/deactivate" , user. id) ) . bearer ( & token) ;
151
- let request = match skip_lock {
152
- None => request. empty ( ) ,
153
- Some ( skip_lock) => request. json ( serde_json:: json!( {
154
- "skip_lock" : skip_lock,
155
- } ) ) ,
156
- } ;
129
+ let request = Request :: post ( format ! ( "/api/admin/v1/users/{}/deactivate" , user. id) )
130
+ . bearer ( & token)
131
+ . empty ( ) ;
157
132
let response = state. request ( request) . await ;
158
133
response. assert_status ( StatusCode :: OK ) ;
159
134
let body: serde_json:: Value = response. json ( ) ;
160
135
161
- // The locked_at timestamp should be the same as the current time, or null if
162
- // not locked
136
+ // The deactivated_at timestamp should be the same as the current time
137
+ assert_eq ! (
138
+ body[ "data" ] [ "attributes" ] [ "deactivated_at" ] ,
139
+ serde_json:: json!( state. clock. now( ) )
140
+ ) ;
141
+
142
+ // Deactivating the user should not lock it
163
143
assert_eq ! (
164
144
body[ "data" ] [ "attributes" ] [ "locked_at" ] ,
165
- if skip_lock. unwrap_or( false ) {
166
- serde_json:: Value :: Null
167
- } else {
168
- serde_json:: json!( state. clock. now( ) )
169
- }
145
+ serde_json:: Value :: Null
170
146
) ;
171
147
172
148
// Make sure to run the jobs in the queue
@@ -179,15 +155,15 @@ mod tests {
179
155
response. assert_status ( StatusCode :: OK ) ;
180
156
let body: serde_json:: Value = response. json ( ) ;
181
157
182
- allow_duplicates ! ( assert_json_snapshot!( body, @r#"
158
+ assert_json_snapshot ! ( body, @r#"
183
159
{
184
160
"data": {
185
161
"type": "user",
186
162
"id": "01FSHN9AG0MZAA6S4AF7CTV32E",
187
163
"attributes": {
188
164
"username": "alice",
189
165
"created_at": "2022-01-16T14:40:00Z",
190
- "locked_at": "2022-01-16T14:40:00Z" ,
166
+ "locked_at": null ,
191
167
"deactivated_at": "2022-01-16T14:40:00Z",
192
168
"admin": false
193
169
},
@@ -199,17 +175,7 @@ mod tests {
199
175
"self": "/api/admin/v1/users/01FSHN9AG0MZAA6S4AF7CTV32E"
200
176
}
201
177
}
202
- "# ) ) ;
203
- }
204
-
205
- #[ sqlx:: test( migrator = "mas_storage_pg::MIGRATOR" ) ]
206
- async fn test_deactivate_user ( pool : PgPool ) {
207
- test_deactivate_user_helper ( pool, Option :: None ) . await ;
208
- }
209
-
210
- #[ sqlx:: test( migrator = "mas_storage_pg::MIGRATOR" ) ]
211
- async fn test_deactivate_user_skip_lock ( pool : PgPool ) {
212
- test_deactivate_user_helper ( pool, Option :: Some ( true ) ) . await ;
178
+ "# ) ;
213
179
}
214
180
215
181
#[ sqlx:: test( migrator = "mas_storage_pg::MIGRATOR" ) ]
@@ -237,14 +203,16 @@ mod tests {
237
203
response. assert_status ( StatusCode :: OK ) ;
238
204
let body: serde_json:: Value = response. json ( ) ;
239
205
240
- // The locked_at timestamp should be different from the current time
241
- assert_ne ! (
242
- body[ "data" ] [ "attributes" ] [ "locked_at " ] ,
206
+ // The deactivated_at timestamp should be the same as the current time
207
+ assert_eq ! (
208
+ body[ "data" ] [ "attributes" ] [ "deactivated_at " ] ,
243
209
serde_json:: json!( state. clock. now( ) )
244
210
) ;
211
+
212
+ // The deactivated_at timestamp should be different from the locked_at timestamp
245
213
assert_ne ! (
214
+ body[ "data" ] [ "attributes" ] [ "deactivated_at" ] ,
246
215
body[ "data" ] [ "attributes" ] [ "locked_at" ] ,
247
- serde_json:: Value :: Null
248
216
) ;
249
217
250
218
// Make sure to run the jobs in the queue
0 commit comments