summaryrefslogtreecommitdiff
path: root/app/models/user.rb
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-31 15:55:43 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-31 15:55:43 +0200
commit464dd4266bdc433805010b5dca428f4cb75c2a81 (patch)
tree47fdf4f065960d49da015eafdf56cb817dcf9ea4 /app/models/user.rb
parent5f17f421b176d48ef556fb379f59bbb7d284b48e (diff)
Group user accounts by role
Replaces the two-way admin/user split with four groups ordered by capability: administration, Redaktion, editors, alumni. alumni takes precedence over capability in role_group, so a retired admin appears at the bottom rather than the top. Forms now offer the three roles as checkboxes rather than a single admin checkbox, with a trailing hidden blank so an empty set can be posted, and user_params permits roles only for admins. Three create buttons prefill the common combinations.
Diffstat (limited to 'app/models/user.rb')
-rw-r--r--app/models/user.rb51
1 files changed, 50 insertions, 1 deletions
diff --git a/app/models/user.rb b/app/models/user.rb
index e1eff059..2e9da86c 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -9,6 +9,8 @@ class User < ApplicationRecord
9 include Authentication 9 include Authentication
10 include Authentication::ByPassword 10 include Authentication::ByPassword
11 11
12 ROLES = %w[redaktion admin alumni].freeze
13
12 # Validations 14 # Validations
13 validates_presence_of :login 15 validates_presence_of :login
14 validates_length_of :login, :within => 1..40 16 validates_length_of :login, :within => 1..40
@@ -22,6 +24,8 @@ class User < ApplicationRecord
22 validates_format_of :email, :with => Authentication.email_regex, 24 validates_format_of :email, :with => Authentication.email_regex,
23 :message => Authentication.bad_email_message 25 :message => Authentication.bad_email_message
24 26
27 validate :roles_are_known
28
25 # Authenticates a user by their login name and unencrypted password. Returns the user or nil. 29 # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
26 def self.authenticate(login, password) 30 def self.authenticate(login, password)
27 return if login.blank? || password.blank? 31 return if login.blank? || password.blank?
@@ -60,7 +64,45 @@ class User < ApplicationRecord
60 end 64 end
61 65
62 def is_admin? 66 def is_admin?
63 !!admin 67 roles.include?("admin")
68 end
69
70 # Compatibility shims for the users form, which posts user[admin] as a
71 # checkbox. Goes away when that form learns about roles.
72 def admin
73 is_admin?
74 end
75
76 def admin?
77 is_admin?
78 end
79
80 def admin=(value)
81 if ActiveModel::Type::Boolean.new.cast(value)
82 self.roles = (roles | ["admin"])
83 else
84 self.roles = (roles - ["admin"])
85 end
86 end
87
88 def redaktion?
89 roles.include?("redaktion")
90 end
91
92 def alumni?
93 roles.include?("alumni")
94 end
95
96 def role_group
97 return :alumni if alumni?
98 return :admin if is_admin?
99 return :redaktion if redaktion?
100 :editor
101 end
102
103 # Human-readable role names, for the list and the forms.
104 def role_labels
105 roles.map { |r| I18n.t("users.roles.#{r}", :default => r) }
64 end 106 end
65 107
66 # otp_secret present == enrolled. otp_pending_secret holds the secret 108 # otp_secret present == enrolled. otp_pending_secret holds the secret
@@ -133,4 +175,11 @@ class User < ApplicationRecord
133 end 175 end
134 true 176 true
135 end 177 end
178
179 private
180
181 def roles_are_known
182 unknown = roles.to_a - ROLES
183 errors.add(:roles, :unknown, :list => unknown.join(", ")) if unknown.any?
184 end
136end 185end