diff options
Diffstat (limited to 'app/models')
| -rw-r--r-- | app/models/node_action.rb | 5 | ||||
| -rw-r--r-- | app/models/user.rb | 20 |
2 files changed, 23 insertions, 2 deletions
diff --git a/app/models/node_action.rb b/app/models/node_action.rb index fec5a062..d619aac5 100644 --- a/app/models/node_action.rb +++ b/app/models/node_action.rb | |||
| @@ -98,8 +98,9 @@ class NodeAction < ApplicationRecord | |||
| 98 | # "detached_from" -- array of unique_names, only when any | 98 | # "detached_from" -- array of unique_names, only when any |
| 99 | # "headline_removed_from" -- array of unique_names, only when any | 99 | # "headline_removed_from" -- array of unique_names, only when any |
| 100 | # | 100 | # |
| 101 | # "otp_enroll" / "otp_disable" / "otp_reset" (second-factor lifecycle; | 101 | # "otp_enroll" / "otp_disable" / "otp_reset" / "user_deactivate" / |
| 102 | # node column nil; participants: the affected User -- the table's first | 102 | # "user_reactivate" (second-factor lifecycle; node column nil; |
| 103 | # participants: the affected User | ||
| 103 | # User-typed subject. otp_disable is self-service; otp_reset is an | 104 | # User-typed subject. otp_disable is self-service; otp_reset is an |
| 104 | # administrator clearing someone else's factor, where actor and | 105 | # administrator clearing someone else's factor, where actor and |
| 105 | # participant differ): | 106 | # participant differ): |
diff --git a/app/models/user.rb b/app/models/user.rb index 2e9da86c..1728521a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb | |||
| @@ -105,6 +105,26 @@ class User < ApplicationRecord | |||
| 105 | roles.map { |r| I18n.t("users.roles.#{r}", :default => r) } | 105 | roles.map { |r| I18n.t("users.roles.#{r}", :default => r) } |
| 106 | end | 106 | end |
| 107 | 107 | ||
| 108 | def deactivate!(actor:) | ||
| 109 | return false if alumni? | ||
| 110 | transaction do | ||
| 111 | update_column(:roles, (roles | ["alumni"]).sort) | ||
| 112 | NodeAction.record!(:participants => [self], :user => actor, | ||
| 113 | :action => "user_deactivate", :target_login => login) | ||
| 114 | end | ||
| 115 | true | ||
| 116 | end | ||
| 117 | |||
| 118 | def reactivate!(actor:) | ||
| 119 | return false unless alumni? | ||
| 120 | transaction do | ||
| 121 | update_column(:roles, (roles - ["alumni"]).sort) | ||
| 122 | NodeAction.record!(:participants => [self], :user => actor, | ||
| 123 | :action => "user_reactivate", :target_login => login) | ||
| 124 | end | ||
| 125 | true | ||
| 126 | end | ||
| 127 | |||
| 108 | # otp_secret present == enrolled. otp_pending_secret holds the secret | 128 | # otp_secret present == enrolled. otp_pending_secret holds the secret |
| 109 | # between QR display and first-code confirmation. otp_consumed_timestep | 129 | # between QR display and first-code confirmation. otp_consumed_timestep |
| 110 | # makes every accepted code single-use (replay guard within the drift | 130 | # makes every accepted code single-use (replay guard within the drift |
