1: <?php
2: /*
3: * SimpleID
4: *
5: * Copyright (C) Kelvin Mo 2021-2025
6: *
7: * This program is free software; you can redistribute it and/or
8: * modify it under the terms of the GNU General Public
9: * License as published by the Free Software Foundation; either
10: * version 2 of the License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program; if not, write to the Free
19: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20: *
21: */
22:
23: namespace SimpleID\Base;
24:
25: use \DateTimeImmutable;
26: use \ReflectionClass;
27: use \Base;
28: use \GenericEventInterface;
29: use Web\Geo;
30: use SimpleID\Store\Storable;
31: use SimpleID\Util\Events\BaseEvent;
32: use SimpleID\Util\Events\GenericEventTrait;
33:
34: /**
35: * Base class to represent an audit event.
36: *
37: * An audit event represents an action that are typically logged for
38: * audit purposes. An audit event is usually an action performed by
39: * a remote user agent affecting a subject (typically a user) or a client.
40: *
41: * This base class automatically collects the following additional
42: * information:
43: *
44: * - the time the event occurred
45: * - the IP address of the remote machine
46: * - the name of the user agent provided by the remote machine
47: * - if the `log_location` configuration variable is set to true,
48: * uses a GeoIP resolver service to resolve the location of the IP
49: * address
50: */
51: class AuditEvent extends BaseEvent {
52:
53: /** @var \DateTimeImmutable */
54: protected $time;
55:
56: /** @var string|null */
57: protected $ip = null;
58:
59: /** @var string|null */
60: protected $userAgent = null;
61:
62: /** @var array<string, string>|null */
63: protected $location = null;
64:
65: /** @var Storable|null */
66: protected $subject;
67:
68: /** @var Storable|null */
69: protected $client;
70:
71: /**
72: * Creates an audit event
73: *
74: * @param Storable $subject the subject affected by the
75: * event
76: * @param Storable $client the client affected by the event
77: */
78: public function __construct(Storable $subject = null, Storable $client = null) {
79: $f3 = Base::instance();
80: $geo = Geo::instance();
81:
82: $this->time = new DateTimeImmutable();
83: $this->ip = $f3->get('IP');
84: $this->userAgent = $f3->get('AGENT');
85:
86: if (($this->ip != null) && $f3->get('config.log_location')) {
87: $location = $geo->location($this->ip);
88: $this->location = ($location === false) ? null : $location;
89: }
90:
91: $this->subject = $subject;
92: $this->client = $client;
93: }
94:
95: /**
96: * Returns the time the event occurred.
97: *
98: * @return \DateTimeImmutable
99: */
100: public function getTime() {
101: return $this->time;
102: }
103:
104: /**
105: * Returns the IP address of the user agent that triggered this event.
106: *
107: * @return string|null the IP address or null if the IP address is not
108: * available
109: */
110: public function getIP() {
111: return $this->ip;
112: }
113:
114: /**
115: * Returns the user agent that triggered this event.
116: *
117: * @return string|null the name of the user agent or null if it is not
118: * available
119: */
120: public function getUserAgent() {
121: return $this->userAgent;
122: }
123:
124: /**
125: * Returns the location information based on the IP address.
126: *
127: * The location information is an array returned by Fat-Free Framework's
128: * `\Web\Geo::location()` function.
129: *
130: * @see http://fatfreeframework.com/3.8/geo#location
131: * @return array<string, string>|null an array containing location information,
132: * or null if the information is not available
133: */
134: public function getLocation() {
135: return $this->location;
136: }
137:
138: /**
139: * Returns the subject (usually the user) affected by this event.
140: *
141: * @return Storable|null the subject affected by this event
142: */
143: public function getSubject() {
144: return $this->subject;
145: }
146:
147: /**
148: * Returns the client affected by this event.
149: *
150: * @return Storable|null the client affected by this event
151: */
152: public function getClient() {
153: return $this->client;
154: }
155:
156: /**
157: * Returns a shortened event name for audit purposes.
158: *
159: * If the event implements GenericEventInterface, this is equivalent to
160: * `getEventName()`. Otherwise, it returns the name of the event class,
161: * without the namespace.
162: *
163: * Classes that do not use GenericEventInterface may wish to
164: * override this method to return a shorter event name.
165: *
166: * @return string
167: */
168: public function getAuditEventName(): string {
169: if ($this instanceof GenericEventInterface) {
170: return $this->getEventName();
171: } else {
172: return (new ReflectionClass($this))->getShortName();
173: }
174: }
175: }
176:
177: ?>