@@ -4,7 +4,7 @@ use actix_session::{Session, SessionExt};
44use actix_web:: HttpRequest ;
55use futures:: TryStreamExt ;
66use mongodb:: bson:: doc;
7- use netsblox_cloud_common:: api:: { self , ClientId , UserRole } ;
7+ use netsblox_cloud_common:: api:: { self , ClientId , UpdateUserData , UserRole } ;
88
99use crate :: {
1010 app_data:: AppData ,
@@ -19,42 +19,63 @@ pub(crate) struct CreateUser {
1919 _private : ( ) ,
2020}
2121
22+ /// Authorization to view a given user
2223#[ derive( Debug ) ]
2324pub ( crate ) struct ViewUser {
2425 pub ( crate ) username : String ,
2526 _private : ( ) ,
2627}
2728
29+ /// Authorization to list all users
2830pub ( crate ) struct ListUsers {
2931 _private : ( ) ,
3032}
3133
34+ /// Authorization to edit the user with the given username
3235pub ( crate ) struct EditUser {
3336 pub ( crate ) username : String ,
3437 _private : ( ) ,
3538}
3639
37- pub ( crate ) struct SetPassword {
38- pub ( crate ) username : String ,
39- _private : ( ) ,
40+ #[ cfg( test) ]
41+ impl EditUser {
42+ pub ( crate ) fn test ( username : String ) -> Self {
43+ Self {
44+ username,
45+ _private : ( ) ,
46+ }
47+ }
4048}
4149
42- pub ( crate ) struct BanUser {
50+ /// Authorization to apply the given updates to the specified user
51+ pub ( crate ) struct UpdateUser {
4352 pub ( crate ) username : String ,
53+ pub ( crate ) update : UpdateUserData ,
4454 _private : ( ) ,
4555}
4656
47- // TODO: make a macro for making it when testing?
4857#[ cfg( test) ]
49- impl EditUser {
50- pub ( crate ) fn test ( username : String ) -> Self {
58+ impl UpdateUser {
59+ pub ( crate ) fn test ( username : String , update : UpdateUserData ) -> Self {
5160 Self {
5261 username,
62+ update,
5363 _private : ( ) ,
5464 }
5565 }
5666}
5767
68+ pub ( crate ) struct SetPassword {
69+ pub ( crate ) username : String ,
70+ _private : ( ) ,
71+ }
72+
73+ pub ( crate ) struct BanUser {
74+ pub ( crate ) username : String ,
75+ _private : ( ) ,
76+ }
77+
78+ // TODO: make a macro for making it when testing?
5879#[ cfg( test) ]
5980impl BanUser {
6081 pub ( crate ) fn test ( username : String ) -> Self {
@@ -99,20 +120,40 @@ pub(crate) async fn try_create_user(
99120 }
100121
101122 let new_user_role = data. role . unwrap_or ( UserRole :: User ) ;
102- let is_privileged = !matches ! ( new_user_role, UserRole :: User ) ;
123+ try_assign_role ( app, req, & new_user_role)
124+ . await
125+ . map ( |_| CreateUser { data, _private : ( ) } )
126+ }
127+
128+ /// Permissions for assigning a given role. Used as a helper method for related functions.
129+ struct AssignRole {
130+ /// The role that the permissions are assigned for.
131+ _role : UserRole ,
132+ _private : ( ) ,
133+ }
134+
135+ async fn try_assign_role (
136+ app : & AppData ,
137+ req : & HttpRequest ,
138+ role : & UserRole ,
139+ ) -> Result < AssignRole , UserError > {
140+ let is_privileged = !matches ! ( role, UserRole :: User ) ;
103141
104142 let is_authorized = if is_privileged {
105143 // only moderators, admins can make privileged users (up to their role)
106144 let username = utils:: get_username ( req) . ok_or ( UserError :: LoginRequiredError ) ?;
107145 let req_role = get_user_role ( app, & username) . await ?;
108- dbg ! ( & req_role, & new_user_role ) ;
109- req_role >= UserRole :: Moderator && req_role >= new_user_role
146+ dbg ! ( & req_role, & role ) ;
147+ req_role >= UserRole :: Moderator && req_role >= * role
110148 } else {
111149 true
112150 } ;
113151
114152 if is_authorized {
115- Ok ( CreateUser { data, _private : ( ) } )
153+ Ok ( AssignRole {
154+ _role : role. to_owned ( ) ,
155+ _private : ( ) ,
156+ } )
116157 } else {
117158 Err ( UserError :: PermissionsError )
118159 }
@@ -211,6 +252,32 @@ pub(crate) async fn try_edit_user(
211252 }
212253}
213254
255+ /// Try to get privileges to apply the given updates to the specified user.
256+ pub ( crate ) async fn try_update_user (
257+ app : & AppData ,
258+ req : & HttpRequest ,
259+ username : & str ,
260+ update : UpdateUserData ,
261+ ) -> Result < UpdateUser , UserError > {
262+ // If setting the group_id, we must be able to edit the group
263+ if let Some ( group_id) = update. group_id . as_ref ( ) {
264+ auth:: try_edit_group ( app, req, group_id) . await ?;
265+ }
266+
267+ // If setting the user role, we must be able to assign those roles
268+ if let Some ( role) = update. role . as_ref ( ) {
269+ try_assign_role ( app, req, role) . await ?;
270+ }
271+
272+ try_edit_user ( app, req, None , username)
273+ . await
274+ . map ( |eu| UpdateUser {
275+ username : eu. username . to_owned ( ) ,
276+ update,
277+ _private : ( ) ,
278+ } )
279+ }
280+
214281pub ( crate ) async fn try_set_password (
215282 app : & AppData ,
216283 req : & HttpRequest ,
0 commit comments