Introduce an "owner" role, and prevent it from being administered

to prevent the owner from being demoted or kicked out.

ref: https://app.fizzy.do/5986089/cards/3213
This commit is contained in:
Mike Dalessio
2025-11-29 13:17:59 -05:00
parent 156a23f1f5
commit edf6b53469
20 changed files with 166 additions and 36 deletions
@@ -18,5 +18,29 @@ class Users::RolesControllerTest < ActionDispatch::IntegrationTest
assert_no_changes -> { users(:david).reload.role } do
put user_role_path(users(:david)), params: { user: { role: "system" } }
end
assert_no_changes -> { users(:david).reload.role } do
put user_role_path(users(:david)), params: { user: { role: "owner" } }
end
end
test "admin cannot demote the owner" do
assert users(:jason).owner?
assert_no_changes -> { users(:jason).reload.role } do
put user_role_path(users(:jason)), params: { user: { role: "admin" } }
end
assert_response :forbidden
end
test "admin cannot change owner role to member" do
assert users(:jason).owner?
assert_no_changes -> { users(:jason).reload.role } do
put user_role_path(users(:jason)), params: { user: { role: "member" } }
end
assert_response :forbidden
end
end
+14
View File
@@ -41,6 +41,20 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
assert_nil User.active.find_by(id: users(:david).id)
end
test "admin cannot deactivate the owner" do
sign_in_as :kevin
assert users(:jason).owner?
assert users(:jason).active
assert_no_difference -> { User.active.count } do
delete user_path(users(:jason))
end
assert_response :forbidden
assert users(:jason).reload.active
end
test "non-admins cannot perform actions" do
sign_in_as :jz
+4
View File
@@ -5,6 +5,10 @@ david:
jz:
email_address: jz@37signals.com
jason:
email_address: jason@37signals.com
staff: true
kevin:
email_address: kevin@37signals.com
staff: true
+7
View File
@@ -12,6 +12,13 @@ jz:
identity: jz
account: 37s_uuid
jason:
id: <%= ActiveRecord::FixtureSet.identify("jason", :uuid) %>
name: Jason
role: owner
identity: jason
account: 37s_uuid
kevin:
id: <%= ActiveRecord::FixtureSet.identify("kevin", :uuid) %>
name: Kevin
+11 -10
View File
@@ -12,17 +12,17 @@ class AccountTest < ActiveSupport::TestCase
assert_equal "/#{account.external_account_id}", account.slug
end
test ".create_with_admin_user creates a new local account" do
test ".create_with_owner creates a new local account" do
Current.without_account do
identity = identities(:david)
account = nil
assert_changes -> { Account.count }, +1 do
assert_changes -> { User.count }, +2 do
account = Account.create_with_admin_user(
account = Account.create_with_owner(
account: {
external_account_id: ActiveRecord::FixtureSet.identify("account-create-with-admin-user-test"),
name: "Account Create With Admin"
external_account_id: ActiveRecord::FixtureSet.identify("account-create-with-owner-test"),
name: "Account Create With Owner"
},
owner: {
name: "David",
@@ -34,13 +34,14 @@ class AccountTest < ActiveSupport::TestCase
assert_not_nil account
assert account.persisted?
assert_equal ActiveRecord::FixtureSet.identify("account-create-with-admin-user-test"), account.external_account_id
assert_equal "Account Create With Admin", account.name
assert_equal ActiveRecord::FixtureSet.identify("account-create-with-owner-test"), account.external_account_id
assert_equal "Account Create With Owner", account.name
admin = account.users.find_by(role: "admin")
assert_equal "David", admin.name
assert_equal "david@37signals.com", admin.identity.email_address
assert_equal "admin", admin.role
owner = account.users.find_by(role: "owner")
assert_equal "David", owner.name
assert_equal "david@37signals.com", owner.identity.email_address
assert_equal "owner", owner.role
assert owner.admin?, "owner should also be considered an admin"
assert_predicate account.system_user, :present?
end
+50
View File
@@ -8,6 +8,56 @@ class User::RoleTest < ActiveSupport::TestCase
assert_not users(:jz).can_administer?(users(:kevin))
end
test "owner can administer admins and members" do
assert users(:jason).can_administer?(users(:kevin))
assert users(:jason).can_administer?(users(:david))
assert users(:jason).can_administer?(users(:jz))
end
test "owner cannot administer themselves" do
assert_not users(:jason).can_administer?(users(:jason))
end
test "admin cannot administer the owner" do
assert_not users(:kevin).can_administer?(users(:jason))
end
test "owner is included in active scope" do
active_users = User.active
assert_includes active_users, users(:jason)
assert_includes active_users, users(:kevin)
assert_includes active_users, users(:david)
assert_not_includes active_users, users(:system)
end
test "owner is also considered an admin" do
assert users(:jason).owner?
assert users(:jason).admin?
assert users(:kevin).admin?
assert_not users(:kevin).owner?
end
test "owner scope returns only active owners" do
owners = accounts("37s").users.owner
assert_includes owners, users(:jason)
assert_not_includes owners, users(:kevin)
assert_not_includes owners, users(:david)
users(:jason).update!(active: false)
assert_not_includes accounts("37s").users.owner, users(:jason)
end
test "admin scope returns active owners and admins" do
admins = accounts("37s").users.admin
assert_includes admins, users(:jason)
assert_includes admins, users(:kevin)
assert_not_includes admins, users(:david)
users(:kevin).update!(active: false)
assert_not_includes accounts("37s").users.admin, users(:kevin)
end
test "can administer board?" do
writebook_board = boards(:writebook)
private_board = boards(:private)