]> BookStack Code Mirror - bookstack/blob - app/Actions/ActivityLogger.php
Added active toggle to webhooks
[bookstack] / app / Actions / ActivityLogger.php
1 <?php
2
3 namespace BookStack\Actions;
4
5 use BookStack\Auth\Permissions\PermissionService;
6 use BookStack\Entities\Models\Entity;
7 use BookStack\Interfaces\Loggable;
8 use Illuminate\Database\Eloquent\Builder;
9 use Illuminate\Support\Facades\Log;
10
11 class ActivityLogger
12 {
13     protected $permissionService;
14
15     public function __construct(PermissionService $permissionService)
16     {
17         $this->permissionService = $permissionService;
18     }
19
20     /**
21      * Add a generic activity event to the database.
22      *
23      * @param string|Loggable $detail
24      */
25     public function add(string $type, $detail = '')
26     {
27         $detailToStore = ($detail instanceof Loggable) ? $detail->logDescriptor() : $detail;
28
29         $activity = $this->newActivityForUser($type);
30         $activity->detail = $detailToStore;
31
32         if ($detail instanceof Entity) {
33             $activity->entity_id = $detail->id;
34             $activity->entity_type = $detail->getMorphClass();
35         }
36
37         $activity->save();
38         $this->setNotification($type);
39         $this->dispatchWebhooks($type, $detail);
40     }
41
42     /**
43      * Get a new activity instance for the current user.
44      */
45     protected function newActivityForUser(string $type): Activity
46     {
47         $ip = request()->ip() ?? '';
48
49         return (new Activity())->forceFill([
50             'type'     => strtolower($type),
51             'user_id'  => user()->id,
52             'ip'       => config('app.env') === 'demo' ? '127.0.0.1' : $ip,
53         ]);
54     }
55
56     /**
57      * Removes the entity attachment from each of its activities
58      * and instead uses the 'extra' field with the entities name.
59      * Used when an entity is deleted.
60      */
61     public function removeEntity(Entity $entity)
62     {
63         $entity->activity()->update([
64             'detail'       => $entity->name,
65             'entity_id'    => null,
66             'entity_type'  => null,
67         ]);
68     }
69
70     /**
71      * Flashes a notification message to the session if an appropriate message is available.
72      */
73     protected function setNotification(string $type): void
74     {
75         $notificationTextKey = 'activities.' . $type . '_notification';
76         if (trans()->has($notificationTextKey)) {
77             $message = trans($notificationTextKey);
78             session()->flash('success', $message);
79         }
80     }
81
82     /**
83      * @param string|Loggable $detail
84      */
85     protected function dispatchWebhooks(string $type, $detail): void
86     {
87         $webhooks = Webhook::query()
88             ->whereHas('trackedEvents', function(Builder $query) use ($type) {
89                 $query->where('event', '=', $type)
90                     ->orWhere('event', '=', 'all');
91             })
92             ->where('active', '=', true)
93             ->get();
94
95         foreach ($webhooks as $webhook) {
96             dispatch(new DispatchWebhookJob($webhook, $type, $detail));
97         }
98     }
99
100     /**
101      * Log out a failed login attempt, Providing the given username
102      * as part of the message if the '%u' string is used.
103      */
104     public function logFailedLogin(string $username)
105     {
106         $message = config('logging.failed_login.message');
107         if (!$message) {
108             return;
109         }
110
111         $message = str_replace('%u', $username, $message);
112         $channel = config('logging.failed_login.channel');
113         Log::channel($channel)->warning($message);
114     }
115 }