diff --git a/AGENTS.md b/AGENTS.md
index 8bdaa4481..203422200 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -68,7 +68,7 @@ Fizzy uses **URL path-based multi-tenancy**:
**Passwordless magic link authentication**:
- Global `Identity` (email-based) can have `Users` in multiple Accounts
-- Users belong to an Account and have roles: admin, member, system
+- Users belong to an Account and have roles: owner, admin, member, system
- Sessions managed via signed cookies
- Board-level access control via `Access` records
@@ -84,7 +84,7 @@ Fizzy uses **URL path-based multi-tenancy**:
**User** → Account membership
- Belongs to Account and Identity
-- Has role (admin/member/system)
+- Has role (owner/admin/member/system)
- Board access via explicit `Access` records
**Board** → Primary organizational unit
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
new file mode 100644
index 000000000..7cccfe4ec
--- /dev/null
+++ b/app/helpers/users_helper.rb
@@ -0,0 +1,8 @@
+module UsersHelper
+ def role_display_name(user)
+ case user.role
+ when "admin" then "Administrator"
+ else user.role.titleize
+ end
+ end
+end
diff --git a/app/models/account.rb b/app/models/account.rb
index 887ce708d..9c445f10e 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -17,10 +17,10 @@ class Account < ApplicationRecord
validates :name, presence: true
class << self
- def create_with_admin_user(account:, owner:)
+ def create_with_owner(account:, owner:)
create!(**account).tap do |account|
account.users.create!(role: :system, name: "System")
- account.users.create!(**owner.reverse_merge(role: "admin"))
+ account.users.create!(**owner.reverse_merge(role: "owner"))
end
end
end
diff --git a/app/models/account/seedeable.rb b/app/models/account/seedeable.rb
index f0592020a..e50c22e96 100644
--- a/app/models/account/seedeable.rb
+++ b/app/models/account/seedeable.rb
@@ -2,6 +2,6 @@ module Account::Seedeable
extend ActiveSupport::Concern
def setup_customer_template
- Account::Seeder.new(self, users.active.where(role: :admin).first).seed
+ Account::Seeder.new(self, users.admin.first).seed
end
end
diff --git a/app/models/signup.rb b/app/models/signup.rb
index bdcf3490d..15ac5873c 100644
--- a/app/models/signup.rb
+++ b/app/models/signup.rb
@@ -54,7 +54,7 @@ class Signup
end
def create_account
- @account = Account.create_with_admin_user(
+ @account = Account.create_with_owner(
account: {
external_account_id: @tenant,
name: generate_account_name
@@ -64,7 +64,7 @@ class Signup
identity: identity
}
)
- @user = @account.users.find_by!(role: :admin)
+ @user = @account.users.find_by!(role: :owner)
@account.setup_customer_template
end
diff --git a/app/models/user/role.rb b/app/models/user/role.rb
index 3c2101f68..e103e94d9 100644
--- a/app/models/user/role.rb
+++ b/app/models/user/role.rb
@@ -2,18 +2,24 @@ module User::Role
extend ActiveSupport::Concern
included do
- enum :role, %i[ admin member system ].index_by(&:itself), scopes: false
+ enum :role, %i[ owner admin member system ].index_by(&:itself), scopes: false
- scope :member, -> { where(role: :member) }
- scope :active, -> { where(active: true, role: %i[ admin member ]) }
+ scope :owner, -> { where(active: true, role: :owner) }
+ scope :admin, -> { where(active: true, role: %i[ owner admin ]) }
+ scope :member, -> { where(active: true, role: :member) }
+ scope :active, -> { where(active: true, role: %i[ owner admin member ]) }
+
+ def admin?
+ super || owner?
+ end
end
def can_change?(other)
- admin? || other == self
+ (admin? && !other.owner?) || other == self
end
def can_administer?(other)
- admin? && other != self
+ admin? && !other.owner? && other != self
end
def can_administer_board?(board)
diff --git a/app/views/account/settings/_user.html.erb b/app/views/account/settings/_user.html.erb
index 45fc77c07..6bc65acd8 100644
--- a/app/views/account/settings/_user.html.erb
+++ b/app/views/account/settings/_user.html.erb
@@ -10,11 +10,13 @@
<%= form_with model: user, url: user_role_path(user), data: { controller: "form" }, method: :patch do | form | %>
-
+
+
+
<% end %>
<%# FIXME: Move this Current.user check to a stimulus controller that just checks for admin? or the like we so we can cache user list %>
diff --git a/app/views/admin/stats/show.html.erb b/app/views/admin/stats/show.html.erb
index 2fe7ce71a..a3ae18c55 100644
--- a/app/views/admin/stats/show.html.erb
+++ b/app/views/admin/stats/show.html.erb
@@ -70,7 +70,7 @@