Class: CommandTower::UserAttributes::Mutate

Inherits:
Object
  • Object
show all
Defined in:
app/services/command_tower/user_attributes/mutate.rb

Overview

Applies exactly one configuration-allowed account attribute change to a user.

Used by modern Me profile services. Callers keep their own authorization boundary; this object only enforces which attributes may change and what values they accept.

Defined Under Namespace

Classes: Outcome

Constant Summary collapse

VALUE_OVERRIDES =

Attributes whose accepted values are not derivable from the column type.

{
  verifier_token: [true, false],
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user:, attributes:, admin_user: nil) ⇒ Mutate

Returns a new instance of Mutate.



78
79
80
81
82
# File 'app/services/command_tower/user_attributes/mutate.rb', line 78

def initialize(user:, attributes:, admin_user: nil)
  @user = user
  @admin_user = admin_user
  @attributes = attributes.symbolize_keys.compact
end

Class Method Details

.assign!Object

Invoked from lib/command_tower/configuration/user/config.rb whenever the changeable attribute list is reconfigured.



53
54
55
# File 'app/services/command_tower/user_attributes/mutate.rb', line 53

def assign!
  @change_rules = nil
end

.call(user:, admin_user: nil, **attributes) ⇒ Object



47
48
49
# File 'app/services/command_tower/user_attributes/mutate.rb', line 47

def call(user:, admin_user: nil, **attributes)
  new(user:, admin_user:, attributes:).call
end

.change_rulesObject



57
58
59
# File 'app/services/command_tower/user_attributes/mutate.rb', line 57

def change_rules
  @change_rules ||= build_change_rules
end

Instance Method Details

#callObject



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'app/services/command_tower/user_attributes/mutate.rb', line 84

def call
  changes = attributes.slice(*change_rules.keys)
  return invalid(modify_attribute: composition_message(changes)) unless changes.size == 1

  attribute, value = changes.first

  type_message = type_message_for(attribute, value)
  return invalid(attribute => type_message) if type_message

  business_message = business_message_for(attribute, value)
  return invalid(attribute => business_message) if business_message

  if attribute == :verifier_token
    user.reset_verifier_token!
  else
    user.update!(attribute => value)
  end

  Outcome.success(user:, attribute:)
end