Skip to content

Commit 644ef04

Browse files
authored
Merge pull request #18226 from Godmartinz/audit-notification-rb-19608
Fixes RB-19608 adds safe guards, adds Audit notification for google workspace, adds tests
2 parents 33839d7 + 48270cb commit 644ef04

File tree

4 files changed

+129
-2
lines changed

4 files changed

+129
-2
lines changed

app/Notifications/AuditNotification.php

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
use Illuminate\Notifications\Notification;
1111
use Illuminate\Support\Facades\Log;
1212
use Illuminate\Support\Str;
13+
use NotificationChannels\GoogleChat\Card;
14+
use NotificationChannels\GoogleChat\GoogleChatChannel;
15+
use NotificationChannels\GoogleChat\GoogleChatMessage;
16+
use NotificationChannels\GoogleChat\Section;
17+
use NotificationChannels\GoogleChat\Widgets\KeyValue;
1318
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
1419
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
1520
use Symfony\Component\Mime\Email;
@@ -33,6 +38,10 @@ public function __construct($params)
3338
//
3439
$this->settings = Setting::getSettings();
3540
$this->params = $params;
41+
$item = $params['item'];
42+
if (!$item || !is_object($item)) {
43+
throw new \InvalidArgumentException('Notification requires a valid item.');
44+
}
3645
}
3746

3847
/**
@@ -51,6 +60,10 @@ public function via()
5160

5261
$notifyBy[] = MicrosoftTeamsChannel::class;
5362
}
63+
if (Setting::getSettings()->webhook_selected == 'google' && Setting::getSettings()->webhook_endpoint) {
64+
Log::debug('using google webhook');
65+
$notifyBy[] = GoogleChatChannel::class;
66+
}
5467
return $notifyBy;
5568
}
5669

@@ -84,21 +97,57 @@ public static function toMicrosoftTeams($params)
8497
$location = $params['location'] ?? '';
8598
$setting = Setting::getSettings();
8699

100+
//if somehow a notification triggers without an item, bail out.
101+
if(!$item || !is_object($item)){
102+
return null;
103+
}
104+
87105
if(!Str::contains($setting->webhook_endpoint, 'workflows')) {
88106
return MicrosoftTeamsMessage::create()
89107
->to($setting->webhook_endpoint)
90108
->type('success')
91-
->title(class_basename(get_class($params['item'])) .' '.trans('general.audited'))
109+
->title(class_basename($item).' '.trans('general.audited'))
92110
->addStartGroupToSection('activityText')
93111
->fact(trans('mail.asset'), $item)
94112
->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->display_name);
95113
}
96-
$message = class_basename(get_class($params['item'])) . ' Audited By '.$admin_user->display_name;
114+
$message = class_basename(get_class($params['item'])) . trans('general.audited_by').' '.$admin_user->display_name;
97115
$details = [
98116
trans('mail.asset') => htmlspecialchars_decode($item->display_name),
99117
trans('mail.notes') => $note ?: '',
100118
trans('general.location') => $location ?: '',
101119
];
102120
return [$message, $details];
103121
}
122+
public function toGoogleChat()
123+
{
124+
$item = $this->params['item'] ?? null;
125+
$admin_user = $this->params['admin'] ?? null;
126+
$note = $this->params['note'] ?? '';
127+
$setting = $this->settings ?? Setting::getSettings();
128+
129+
$title = '<strong>' . class_basename($item) . ' ' . trans('general.audited') . '</strong>';
130+
$subtitle = htmlspecialchars_decode($item->display_name ?? '');
131+
\Log::debug('Google Chat audit payload', [
132+
'title' => $title,
133+
'subtitle' => $subtitle,
134+
'admin' => $admin_user->display_name,
135+
'note' => $note,
136+
]);
137+
return GoogleChatMessage::create()
138+
->to($setting->webhook_endpoint)
139+
->card(
140+
Card::create()
141+
->header($title, $subtitle)
142+
->section(
143+
Section::create(
144+
KeyValue::create(
145+
trans('general.audited_by'),
146+
$admin_user?->display_name ?? '',
147+
$note ?? ''
148+
)->onClick(route('hardware.show', $item->id))
149+
)
150+
)
151+
);
152+
}
104153
}

resources/lang/en-US/general.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
'accept_items' => 'Accept Items',
4040
'audit' => 'Audit',
4141
'audited' => 'Audited',
42+
'audited_by' => 'Audited By',
4243
'audits' => 'Audits',
4344
'audit_report' => 'Audit Log',
4445
'assets' => 'Assets',
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
namespace Tests\Feature\Notifications\Webhooks;
3+
4+
use App\Models\Asset;
5+
use App\Models\User;
6+
use App\Notifications\AuditNotification;
7+
use Illuminate\Support\Facades\Notification;
8+
use PHPUnit\Framework\Attributes\Group;
9+
use Tests\TestCase;
10+
use Tests\Support\Settings;
11+
12+
#[Group('notifications')]
13+
class NotificationTests extends TestCase
14+
{
15+
protected function setUp(): void
16+
{
17+
parent::setUp();
18+
19+
Notification::fake();
20+
}
21+
public function testAuditNotificationThrowsWhenItemIsNull()
22+
{
23+
try {
24+
new AuditNotification([
25+
'item' => null,
26+
]);
27+
$this->fail('Expected Error was not thrown');
28+
} catch (\Throwable $e) {
29+
$this->assertInstanceOf(\InvalidArgumentException::class, $e);
30+
$this->assertSame('Notification requires a valid item.', $e->getMessage());
31+
}
32+
}
33+
34+
public function testAuditNotificationFires()
35+
{
36+
$webhook_options = [
37+
'enableSlackWebhook',
38+
'enableMicrosoftTeamsWebhook',
39+
'enableGoogleChatWebhook'
40+
];
41+
42+
Notification::fake();
43+
//tests every webhook option
44+
foreach($webhook_options as $option) {
45+
46+
$this->settings->{$option}();
47+
48+
$user = User::factory()->create();
49+
$item = Asset::factory()->create();
50+
51+
try {
52+
$user->notify(new \App\Notifications\AuditNotification([
53+
'item' => $item,
54+
]));
55+
} catch (\InvalidArgumentException $e) {
56+
$this->fail("AuditNotification threw for [{$option}]: {$e->getMessage()}");
57+
}
58+
}
59+
Notification::assertSentTimes(AuditNotification::class, count($webhook_options));
60+
}
61+
}

tests/Support/Settings.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,22 @@ public function enableSlackWebhook(): Settings
9393
'webhook_channel' => '#it',
9494
]);
9595
}
96+
public function enableMicrosoftTeamsWebhook(): Settings
97+
{
98+
return $this->update([
99+
'webhook_selected' => 'microsoft',
100+
'webhook_endpoint' => 'https://defaultd07ceb04416641fca1b9d3e0ac7600.84.environment.api.powerplatform.com:443/powerautomate/automations/direct/workflows/1babbc7a3cdd4cf99c0fbed4367cf147/triggers/manual/paths/invoke?api-version=1&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=sVXmAYF5luz3oOEjvN-G7mJqEEvFjBTuAG8c3Qmkg',
101+
]);
102+
}
103+
104+
public function enableGoogleChatWebhook(): Settings
105+
{
106+
return $this->update([
107+
'webhook_selected' => 'google',
108+
'webhook_botname' => 'SnipeBot5000',
109+
'webhook_endpoint' => 'https://chat.googleapis.com/v1/spaces/AAAATQckuT4/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=bZDaFDK4lO78HhHmC8BEWI6aAKkgqX2gFv2gHVAc8',
110+
]);
111+
}
96112

97113
public function disableSlackWebhook(): Settings
98114
{

0 commit comments

Comments
 (0)