@@ -522,8 +522,8 @@ def test_administrator_cannot_disable_self(access_token):
522522 delete_admin (access_token , administrator_admin ["username" ])
523523
524524
525- def test_administrator_cannot_modify_other_administrator (access_token ):
526- """An administrator cannot edit another administrator account ."""
525+ def test_administrator_can_modify_other_non_owner_admin (access_token ):
526+ """An admin with admins.update can edit another non-owner admin, regardless of role id ."""
527527 admin_a = create_admin (access_token )
528528 admin_b = create_admin (access_token )
529529 set_admin_role (admin_a ["username" ], 2 )
@@ -544,15 +544,14 @@ def test_administrator_cannot_modify_other_administrator(access_token):
544544 url = f"/api/admin/{ admin_b ['username' ]} " ,
545545 json = {
546546 "status" : "active" ,
547- "note" : "should-fail " ,
547+ "note" : "updated-by-admin " ,
548548 },
549549 headers = {"Authorization" : f"Bearer { admin_a_token } " },
550550 )
551551
552- assert response .status_code == status .HTTP_403_FORBIDDEN
552+ assert response .status_code == status .HTTP_200_OK
553+ assert response .json ()["note" ] == "updated-by-admin"
553554 finally :
554- set_admin_role (admin_a ["username" ], 3 )
555- set_admin_role (admin_b ["username" ], 3 )
556555 delete_admin (access_token , admin_a ["username" ])
557556 delete_admin (access_token , admin_b ["username" ])
558557
@@ -1236,6 +1235,48 @@ def test_create_admin_with_custom_role(access_token):
12361235 client .delete (f"/api/admin-role/{ role ['id' ]} " , headers = {"Authorization" : f"Bearer { access_token } " })
12371236
12381237
1238+ def test_custom_role_with_admin_update_can_modify_administrator (access_token ):
1239+ """A custom role with admins.update can modify role_id=2 admins."""
1240+ role_response = client .post (
1241+ "/api/admin-role" ,
1242+ headers = auth_headers (access_token ),
1243+ json = {
1244+ "name" : unique_name ("admin_update_role" ),
1245+ "permissions" : {"admins" : {"update" : True }},
1246+ "limits" : {
1247+ "max_users" : None ,
1248+ "data_limit_min" : None ,
1249+ "data_limit_max" : None ,
1250+ "expire_min" : None ,
1251+ "expire_max" : None ,
1252+ "max_hwid_per_user" : None ,
1253+ },
1254+ "features" : {"can_use_reset_strategy" : True , "can_use_next_plan" : True },
1255+ "access" : {"require_template" : False , "allowed_template_ids" : None , "allowed_group_ids" : None },
1256+ },
1257+ )
1258+ assert role_response .status_code == status .HTTP_201_CREATED
1259+ role = role_response .json ()
1260+
1261+ actor = create_admin (access_token , role_id = role ["id" ])
1262+ target = create_admin (access_token , role_id = 2 )
1263+ try :
1264+ actor_token = _login (actor ["username" ], actor ["password" ])
1265+
1266+ response = client .put (
1267+ f"/api/admin/{ target ['username' ]} " ,
1268+ json = {"note" : "custom-role-update" },
1269+ headers = auth_headers (actor_token ),
1270+ )
1271+
1272+ assert response .status_code == status .HTTP_200_OK
1273+ assert response .json ()["note" ] == "custom-role-update"
1274+ finally :
1275+ delete_admin (access_token , actor ["username" ])
1276+ delete_admin (access_token , target ["username" ])
1277+ client .delete (f"/api/admin-role/{ role ['id' ]} " , headers = auth_headers (access_token ))
1278+
1279+
12391280# ---------------------------------------------------------------------------
12401281# Admin data_limit, status, and limited-access tests
12411282# ---------------------------------------------------------------------------
0 commit comments