Class: Aikido::Zen::Actor

Inherits:
Object
  • Object
show all
Defined in:
lib/aikido/zen/actor.rb

Overview

Represents someone connecting to the application and making requests.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id:, name: nil, ip: Aikido::Zen.current_context&.request&.client_ip, first_seen_at: Time.now.utc, last_seen_at: first_seen_at) ⇒ Actor

Returns a new instance of Actor.

Parameters:

  • id (String)
  • name (String, nil) (defaults to: nil)
  • ip (String, nil) (defaults to: Aikido::Zen.current_context&.request&.client_ip)
  • first_seen_at (Time) (defaults to: Time.now.utc)
  • last_seen_at (Time) (defaults to: first_seen_at)


65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/aikido/zen/actor.rb', line 65

def initialize(
  id:,
  name: nil,
  ip: Aikido::Zen.current_context&.request&.client_ip,
  first_seen_at: Time.now.utc,
  last_seen_at: first_seen_at
)
  @id = id
  @name = name
  @ip = Concurrent::AtomicReference.new(ip)
  @first_seen_at = first_seen_at
  @last_seen_at = Concurrent::AtomicReference.new(last_seen_at)
end

Instance Attribute Details

#first_seen_atTime (readonly)

Returns:

  • (Time)


58
59
60
# File 'lib/aikido/zen/actor.rb', line 58

def first_seen_at
  @first_seen_at
end

#idString (readonly)

Returns a unique identifier for this user.

Returns:

  • (String)

    a unique identifier for this user.



52
53
54
# File 'lib/aikido/zen/actor.rb', line 52

def id
  @id
end

#nameString? (readonly)

Returns an optional name to display in the Aikido UI.

Returns:

  • (String, nil)

    an optional name to display in the Aikido UI.



55
56
57
# File 'lib/aikido/zen/actor.rb', line 55

def name
  @name
end

Class Method Details

.from_json(data) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/aikido/zen/actor.rb', line 41

def self.from_json(data)
  new(
    id: data[:id],
    name: data[:name],
    ip: data[:lastIpAddress],
    first_seen_at: Time.at(data[:firstSeenAt] / 1000),
    last_seen_at: Time.at(data[:lastSeenAt] / 1000)
  )
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



127
128
129
# File 'lib/aikido/zen/actor.rb', line 127

def ==(other)
  other.is_a?(Actor) && id == other.id
end

#as_jsonObject



136
137
138
139
140
141
142
143
144
# File 'lib/aikido/zen/actor.rb', line 136

def as_json
  {
    id: id,
    name: name,
    lastIpAddress: ip,
    firstSeenAt: first_seen_at.to_i * 1000,
    lastSeenAt: last_seen_at.to_i * 1000
  }.compact
end

#hashObject



132
133
134
# File 'lib/aikido/zen/actor.rb', line 132

def hash
  id.hash
end

#ipString?

Returns the IP address last used by this user, if available.

Returns:

  • (String, nil)

    the IP address last used by this user, if available.



85
86
87
# File 'lib/aikido/zen/actor.rb', line 85

def ip
  @ip.get
end

#last_seen_atTime

Returns:

  • (Time)


80
81
82
# File 'lib/aikido/zen/actor.rb', line 80

def last_seen_at
  @last_seen_at.get
end

#merge(other) ⇒ Aikido::Zen::Actor Also known as: |

Merges the actor with another actor.

Parameters:

Returns:



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/aikido/zen/actor.rb', line 108

def merge(other)
  older = (first_seen_at < other.first_seen_at) ? self : other
  newer = (last_seen_at > other.last_seen_at) ? self : other

  self.class.new(
    id: @id,
    name: newer.name,
    ip: newer.ip,
    first_seen_at: older.first_seen_at,
    last_seen_at: newer.last_seen_at
  )
end

#to_aikido_actorself

Returns:

  • (self)


123
124
125
# File 'lib/aikido/zen/actor.rb', line 123

def to_aikido_actor
  self
end

#update(seen_at: Time.now.utc, ip: Aikido::Zen.current_context&.request&.client_ip) ⇒ void

This method returns an undefined value.

Atomically update the last IP used by the user, and the last time they’ve been “seen” connecting to the app.

Parameters:

  • ip (String, nil) (defaults to: Aikido::Zen.current_context&.request&.client_ip)

    the last-seen IP address for the user. If nil and we had a non-empty value before, we won’t update it. Defaults to the current HTTP request’s IP address, if any.

  • seen_at (Time) (defaults to: Time.now.utc)

    the time at which we’re making the update. We will always keep the most recent time if this conflicts with the current value.



99
100
101
102
# File 'lib/aikido/zen/actor.rb', line 99

def update(seen_at: Time.now.utc, ip: Aikido::Zen.current_context&.request&.client_ip)
  @last_seen_at.try_update { |last_seen_at| [last_seen_at, seen_at].max }
  @ip.try_update { |last_ip| [ip, last_ip].compact.first }
end