@@ -46,4 +46,80 @@ def attach_verified_alias(user, email:, primary: true)
4646 expect ( response ) . to redirect_to ( settings_team_path ( team ) )
4747 end
4848 end
49+
50+ describe "PATCH /teams/:team_id/team_members/:id" do
51+ it "blocks non-admins from changing roles" do
52+ attach_verified_alias ( member , email : "member@example.com" )
53+ sign_in ( email : "member@example.com" )
54+
55+ member_record = team . team_members . find_by ( user : member )
56+ patch settings_team_team_member_path ( team , member_record ) , params : { role : "admin" }
57+
58+ expect ( response ) . to redirect_to ( settings_team_path ( team ) )
59+ expect ( member_record . reload . role ) . to eq ( "member" )
60+ end
61+
62+ it "allows admins to promote members to admin" do
63+ attach_verified_alias ( admin , email : "admin@example.com" )
64+ sign_in ( email : "admin@example.com" )
65+
66+ member_record = team . team_members . find_by ( user : member )
67+ patch settings_team_team_member_path ( team , member_record ) , params : { role : "admin" }
68+
69+ expect ( response ) . to redirect_to ( settings_team_path ( team ) )
70+ expect ( member_record . reload . role ) . to eq ( "admin" )
71+ end
72+
73+ it "allows admins to demote other admins to members" do
74+ attach_verified_alias ( admin , email : "admin@example.com" )
75+ sign_in ( email : "admin@example.com" )
76+
77+ other_admin = create ( :user , password : "secret" , password_confirmation : "secret" )
78+ other_admin_record = create ( :team_member , team : team , user : other_admin , role : "admin" )
79+
80+ patch settings_team_team_member_path ( team , other_admin_record ) , params : { role : "member" }
81+
82+ expect ( response ) . to redirect_to ( settings_team_path ( team ) )
83+ expect ( other_admin_record . reload . role ) . to eq ( "member" )
84+ end
85+
86+ it "prevents admin from removing their own admin status" do
87+ attach_verified_alias ( admin , email : "admin@example.com" )
88+ sign_in ( email : "admin@example.com" )
89+
90+ admin_record = team . team_members . find_by ( user : admin )
91+ patch settings_team_team_member_path ( team , admin_record ) , params : { role : "member" }
92+
93+ expect ( response ) . to redirect_to ( settings_team_path ( team ) )
94+ expect ( flash [ :alert ] ) . to include ( "cannot remove your own admin status" )
95+ expect ( admin_record . reload . role ) . to eq ( "admin" )
96+ end
97+
98+ it "prevents demoting the last admin when there are two admins and one tries to demote the other after becoming the only admin" do
99+ # Create a second admin who will try to demote the first
100+ other_admin = create ( :user , password : "secret" , password_confirmation : "secret" )
101+ attach_verified_alias ( other_admin , email : "other_admin@example.com" )
102+ create ( :team_member , team : team , user : other_admin , role : "admin" )
103+
104+ sign_in ( email : "other_admin@example.com" )
105+
106+ # Demote the first admin - this should work since there are 2 admins
107+ admin_record = team . team_members . find_by ( user : admin )
108+ patch settings_team_team_member_path ( team , admin_record ) , params : { role : "member" }
109+ expect ( admin_record . reload . role ) . to eq ( "member" )
110+
111+ # Now other_admin is the only admin
112+ # Try to demote them using the first admin (now just a member, so should fail authorization)
113+ attach_verified_alias ( admin , email : "admin@example.com" )
114+ sign_in ( email : "admin@example.com" )
115+
116+ other_admin_record = team . team_members . find_by ( user : other_admin )
117+ patch settings_team_team_member_path ( team , other_admin_record ) , params : { role : "member" }
118+
119+ expect ( response ) . to redirect_to ( settings_team_path ( team ) )
120+ expect ( flash [ :alert ] ) . to eq ( "Admins only" )
121+ expect ( other_admin_record . reload . role ) . to eq ( "admin" )
122+ end
123+
124+ end
49125end
0 commit comments