Merge remote-tracking branch 'origin/develop'
This commit is contained in:
2
.github/workflows/codacy-analysis.yml
vendored
2
.github/workflows/codacy-analysis.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.5
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.7
|
||||
with:
|
||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||
# You can also omit the token and run the tools that support default configurations
|
||||
|
||||
@@ -133,8 +133,17 @@ class Handler extends ExceptionHandler
|
||||
// This is traaaaash but it handles models that are not found while using route model binding :(
|
||||
// The only alternative is to set that at *each* route, which is crazypants
|
||||
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
|
||||
$ids = method_exists($e, 'getIds') ? $e->getIds() : [];
|
||||
|
||||
// This gets the MVC model name from the exception and formats in a way that's less fugly
|
||||
if (in_array('bulkedit', $ids, true)) {
|
||||
$error_array = session()->get('bulk_asset_errors');
|
||||
return redirect()
|
||||
->route('hardware.bulkedit')
|
||||
->withErrors($error_array, 'bulk_asset_errors')
|
||||
->withInput();
|
||||
}
|
||||
|
||||
// This gets the MVC model name from the exception and formats in a way that's less fugly
|
||||
$model_name = strtolower(implode(" ", preg_split('/(?=[A-Z])/', last(explode('\\', $e->getModel())))));
|
||||
$route = str_plural(strtolower(last(explode('\\', $e->getModel())))).'.index';
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ class AssetModelsController extends Controller
|
||||
$assetmodel = $request->handleImages($assetmodel);
|
||||
|
||||
if ($assetmodel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.create.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new AssetModelsTransformer)->transformAssetModel($assetmodel), trans('admin/models/message.create.success')));
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));
|
||||
|
||||
@@ -207,7 +207,7 @@ class AssetModelsController extends Controller
|
||||
$assetmodel = AssetModel::findOrFail($id);
|
||||
$assetmodel->fill($request->all());
|
||||
$assetmodel = $request->handleImages($assetmodel);
|
||||
|
||||
|
||||
/**
|
||||
* Allow custom_fieldset_id to override and populate fieldset_id.
|
||||
* This is stupid, but required for legacy API support.
|
||||
@@ -222,7 +222,7 @@ class AssetModelsController extends Controller
|
||||
|
||||
|
||||
if ($assetmodel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.update.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new AssetModelsTransformer)->transformAssetModel($assetmodel), trans('admin/models/message.update.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));
|
||||
|
||||
@@ -161,6 +161,7 @@ class BulkAssetsController extends Controller
|
||||
|
||||
$models = $assets->unique('model_id');
|
||||
$modelNames = [];
|
||||
|
||||
foreach($models as $model) {
|
||||
$modelNames[] = $model->model->name;
|
||||
}
|
||||
@@ -196,7 +197,6 @@ class BulkAssetsController extends Controller
|
||||
|
||||
case 'edit':
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
return view('hardware/bulk')
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
@@ -224,11 +224,8 @@ class BulkAssetsController extends Controller
|
||||
$error_array = array();
|
||||
|
||||
// Get the back url from the session and then destroy the session
|
||||
$bulk_back_url = route('hardware.index');
|
||||
|
||||
if ($request->session()->has('bulk_back_url')) {
|
||||
$bulk_back_url = $request->session()->pull('bulk_back_url');
|
||||
}
|
||||
$bulk_back_url = $request->session()->pull('bulk_back_url', url()->previous());
|
||||
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
|
||||
@@ -543,7 +540,13 @@ class BulkAssetsController extends Controller
|
||||
} // end asset foreach
|
||||
|
||||
if ($has_errors > 0) {
|
||||
return redirect($bulk_back_url)->with('bulk_asset_errors', $error_array);
|
||||
session()->put('bulkedit_ids', $request->input('ids'));
|
||||
session()->put('bulk_asset_errors',$error_array);
|
||||
|
||||
return redirect()
|
||||
->route('hardware.bulkedit')
|
||||
->with('bulk_asset_errors', $error_array)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success'));
|
||||
@@ -735,4 +738,33 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function bulkEditForm(): View|RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
$asset_ids = session()->pull('bulkedit_ids', []);
|
||||
|
||||
if (empty($asset_ids)) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
}
|
||||
|
||||
$assets = Asset::with('model')->withTrashed()->whereIn('id', $asset_ids)->get();
|
||||
|
||||
if ($assets->isEmpty()) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.update.assets_do_not_exist_or_are_invalid'));
|
||||
}
|
||||
|
||||
$models = $assets->unique('model_id');
|
||||
$modelNames = [];
|
||||
foreach ($models as $model) {
|
||||
$modelNames[] = $model->model->name;
|
||||
}
|
||||
|
||||
return view('hardware/bulk')
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('models', $models->pluck(['model']))
|
||||
->with('modelNames', $modelNames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ namespace App\Listeners;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Mail\CheckinAccessoryMail;
|
||||
use App\Mail\CheckinComponentMail;
|
||||
use App\Mail\CheckinLicenseMail;
|
||||
use App\Mail\CheckoutAccessoryMail;
|
||||
use App\Mail\CheckoutAssetMail;
|
||||
use App\Mail\CheckinAssetMail;
|
||||
use App\Mail\CheckoutComponentMail;
|
||||
use App\Mail\CheckoutConsumableMail;
|
||||
use App\Mail\CheckoutLicenseMail;
|
||||
use App\Models\Accessory;
|
||||
@@ -22,9 +24,11 @@ use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckinAccessoryNotification;
|
||||
use App\Notifications\CheckinAssetNotification;
|
||||
use App\Notifications\CheckinComponentNotification;
|
||||
use App\Notifications\CheckinLicenseSeatNotification;
|
||||
use App\Notifications\CheckoutAccessoryNotification;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use App\Notifications\CheckoutComponentNotification;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use App\Notifications\CheckoutLicenseSeatNotification;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
@@ -39,7 +43,7 @@ use Osama\LaravelTeamsNotification\TeamsNotification;
|
||||
class CheckoutableListener
|
||||
{
|
||||
private array $skipNotificationsFor = [
|
||||
Component::class,
|
||||
// Component::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -145,7 +149,6 @@ class CheckoutableListener
|
||||
$shouldSendEmailToUser = $this->checkoutableCategoryShouldSendEmail($event->checkoutable);
|
||||
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress();
|
||||
$shouldSendWebhookNotification = $this->shouldSendWebhookNotification();
|
||||
|
||||
if (!$shouldSendEmailToUser && !$shouldSendEmailToAlertAddress && !$shouldSendWebhookNotification) {
|
||||
return;
|
||||
}
|
||||
@@ -269,6 +272,9 @@ class CheckoutableListener
|
||||
case LicenseSeat::class:
|
||||
$notificationClass = CheckinLicenseSeatNotification::class;
|
||||
break;
|
||||
case Component::class:
|
||||
$notificationClass = CheckinComponentNotification::class;
|
||||
break;
|
||||
}
|
||||
|
||||
Log::debug('Notification class: '.$notificationClass);
|
||||
@@ -299,6 +305,9 @@ class CheckoutableListener
|
||||
case LicenseSeat::class:
|
||||
$notificationClass = CheckoutLicenseSeatNotification::class;
|
||||
break;
|
||||
case Component::class:
|
||||
$notificationClass = CheckoutComponentNotification::class;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,6 +319,7 @@ class CheckoutableListener
|
||||
Asset::class => CheckoutAssetMail::class,
|
||||
LicenseSeat::class => CheckoutLicenseMail::class,
|
||||
Consumable::class => CheckoutConsumableMail::class,
|
||||
Component::class => CheckoutComponentMail::class,
|
||||
];
|
||||
$mailable= $lookup[get_class($event->checkoutable)];
|
||||
|
||||
@@ -322,8 +332,8 @@ class CheckoutableListener
|
||||
Accessory::class => CheckinAccessoryMail::class,
|
||||
Asset::class => CheckinAssetMail::class,
|
||||
LicenseSeat::class => CheckinLicenseMail::class,
|
||||
Component::class => CheckinComponentMail::class,
|
||||
];
|
||||
|
||||
$mailable= $lookup[get_class($event->checkoutable)];
|
||||
|
||||
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
|
||||
@@ -469,7 +479,8 @@ class CheckoutableListener
|
||||
return match (true) {
|
||||
$checkoutable instanceof Asset => $checkoutable->model->category,
|
||||
$checkoutable instanceof Accessory,
|
||||
$checkoutable instanceof Consumable => $checkoutable->category,
|
||||
$checkoutable instanceof Consumable,
|
||||
$checkoutable instanceof Component => $checkoutable->category,
|
||||
$checkoutable instanceof LicenseSeat => $checkoutable->license->category,
|
||||
};
|
||||
}
|
||||
|
||||
71
app/Mail/CheckinComponentMail.php
Normal file
71
app/Mail/CheckinComponentMail.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Component;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckinComponentMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(Component $component, $checkedOutTo, User $checkedInby, $note)
|
||||
{
|
||||
$this->item = $component;
|
||||
$this->target = $checkedOutTo;
|
||||
$this->admin = $checkedInby;
|
||||
$this->note = $note;
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
$from = new Address(config('mail.from.address'), config('mail.from.name'));
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans('mail.Confirm_component_checkin'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
markdown: 'mail.markdown.checkin-component',
|
||||
with: [
|
||||
'item' => $this->item,
|
||||
'admin' => $this->admin,
|
||||
'note' => $this->note,
|
||||
'target' => $this->target,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
82
app/Mail/CheckoutComponentMail.php
Normal file
82
app/Mail/CheckoutComponentMail.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Component;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckoutComponentMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(Component $component, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
|
||||
{
|
||||
$this->item = $component;
|
||||
$this->admin = $checkedOutBy;
|
||||
$this->note = $note;
|
||||
$this->target = $checkedOutTo;
|
||||
$this->acceptance = $acceptance;
|
||||
$this->qty = $component->assets->first()?->pivot?->assigned_qty;
|
||||
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
$from = new Address(config('mail.from.address'), config('mail.from.name'));
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans('mail.Confirm_component_delivery'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
|
||||
$eula = $this->item->getEula();
|
||||
$req_accept = $this->item->requireAcceptance();
|
||||
|
||||
$accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
|
||||
|
||||
return new Content(
|
||||
markdown: 'mail.markdown.checkout-component',
|
||||
with: [
|
||||
'item' => $this->item,
|
||||
'admin' => $this->admin,
|
||||
'note' => $this->note,
|
||||
'target' => $this->target,
|
||||
'eula' => $eula,
|
||||
'req_accept' => $req_accept,
|
||||
'accept_url' => $accept_url,
|
||||
'qty' => $this->qty,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\HasUploads;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
@@ -203,6 +205,36 @@ class Component extends SnipeModel
|
||||
{
|
||||
return $this->belongsTo(\App\Models\Manufacturer::class, 'manufacturer_id');
|
||||
}
|
||||
/**
|
||||
* Determine whether this asset requires acceptance by the assigned user
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return bool
|
||||
*/
|
||||
public function requireAcceptance()
|
||||
{
|
||||
return $this->category->require_acceptance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for a category-specific EULA, and if that doesn't exist,
|
||||
* checks for a settings level EULA
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return string | false
|
||||
*/
|
||||
public function getEula()
|
||||
{
|
||||
if ($this->category->eula_text) {
|
||||
return Helper::parseEscapedMarkedown($this->category->eula_text);
|
||||
} elseif ((Setting::getSettings()->default_eula_text) && ($this->category->use_default_eula == '1')) {
|
||||
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the component -> action logs relationship
|
||||
@@ -248,6 +280,19 @@ class Component extends SnipeModel
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to send a checkin/checkout email based on
|
||||
* asset model category
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return bool
|
||||
*/
|
||||
public function checkin_email()
|
||||
{
|
||||
return $this->category?->checkin_email;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check how many items within a component are remaining
|
||||
|
||||
165
app/Notifications/CheckinComponentNotification.php
Normal file
165
app/Notifications/CheckinComponentNotification.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Component;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Channels\SlackWebhookChannel;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Str;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
class CheckinComponentNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param $params
|
||||
*/
|
||||
public function __construct(Component $component, $checkedOutTo, User $checkedInBy, $note)
|
||||
{
|
||||
$this->target = $checkedOutTo;
|
||||
$this->item = $component;
|
||||
$this->admin = $checkedInBy;
|
||||
$this->note = $note;
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'google' && Setting::getSettings()->webhook_endpoint) {
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft' && Setting::getSettings()->webhook_endpoint) {
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = SlackWebhookChannel::class;
|
||||
}
|
||||
|
||||
return $notifyBy;
|
||||
}
|
||||
|
||||
public function toSlack()
|
||||
{
|
||||
$target = $this->target;
|
||||
$admin = $this->admin;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
$botname = ($this->settings->webhook_botname) ? $this->settings->webhook_botname : 'Snipe-Bot';
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
if ($admin) {
|
||||
$fields = [
|
||||
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
$fields[trans('general.location')] = $item->location->name;
|
||||
}
|
||||
|
||||
if ($item->company) {
|
||||
$fields[trans('general.company')] = $item->company->name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$fields = [
|
||||
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
'By' => 'CLI tool',
|
||||
];
|
||||
}
|
||||
|
||||
return (new SlackMessage)
|
||||
->content(':arrow_down: :package: '.trans('mail.Component_checkin_notification'))
|
||||
->from($botname)
|
||||
->to($channel)
|
||||
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
|
||||
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
|
||||
->fields($fields)
|
||||
->content($note);
|
||||
});
|
||||
}
|
||||
public function toMicrosoftTeams()
|
||||
{
|
||||
$target = $this->target;
|
||||
$admin = $this->admin;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
if(!Str::contains(Setting::getSettings()->webhook_endpoint, 'workflows')) {
|
||||
return MicrosoftTeamsMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->type('success')
|
||||
->addStartGroupToSection('activityTitle')
|
||||
->title(trans('mail.Component_checkin_notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'header')
|
||||
->fact(trans('mail.Component_checkin_notification')." by ", $admin->present()->fullName() ?: 'CLI tool')
|
||||
->fact(trans('mail.checkedin_from'), $target->present()->fullName())
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.Component_checkin_notification');
|
||||
$details = [
|
||||
trans('mail.checkedin_from')=> $target->present()->fullName(),
|
||||
trans('mail.Component_checkin_notification')." by " => $admin->present()->fullName() ?: 'CLI tool',
|
||||
trans('admin/consumables/general.remaining') => $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
|
||||
return array($message, $details);
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Component_checkin_notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.checkedin_from') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
)
|
||||
->onClick(route('components.show', $item->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
164
app/Notifications/CheckoutComponentNotification.php
Normal file
164
app/Notifications/CheckoutComponentNotification.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Component;
|
||||
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Channels\SlackWebhookChannel;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Str;
|
||||
use NotificationChannels\GoogleChat\Card;
|
||||
use NotificationChannels\GoogleChat\GoogleChatChannel;
|
||||
use NotificationChannels\GoogleChat\GoogleChatMessage;
|
||||
use NotificationChannels\GoogleChat\Section;
|
||||
use NotificationChannels\GoogleChat\Widgets\KeyValue;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
|
||||
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
|
||||
class CheckoutComponentNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param $params
|
||||
*/
|
||||
public function __construct(Component $component, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
|
||||
{
|
||||
$this->item = $component;
|
||||
$this->admin = $checkedOutBy;
|
||||
$this->note = $note;
|
||||
$this->target = $checkedOutTo;
|
||||
$this->acceptance = $acceptance;
|
||||
$this->qty = $component->checkout_qty;
|
||||
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**`
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function via()
|
||||
{
|
||||
$notifyBy = [];
|
||||
if (Setting::getSettings()->webhook_selected == 'google' && Setting::getSettings()->webhook_endpoint) {
|
||||
|
||||
$notifyBy[] = GoogleChatChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'microsoft' && Setting::getSettings()->webhook_endpoint) {
|
||||
|
||||
$notifyBy[] = MicrosoftTeamsChannel::class;
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
|
||||
$notifyBy[] = SlackWebhookChannel::class;
|
||||
}
|
||||
|
||||
return $notifyBy;
|
||||
}
|
||||
|
||||
public function toSlack()
|
||||
{
|
||||
$target = $this->target;
|
||||
$admin = $this->admin;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
$botname = ($this->settings->webhook_botname) ? $this->settings->webhook_botname : 'Snipe-Bot';
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
$fields[trans('general.location')] = $item->location->name;
|
||||
}
|
||||
|
||||
if ($item->company) {
|
||||
$fields[trans('general.company')] = $item->company->name;
|
||||
}
|
||||
|
||||
return (new SlackMessage)
|
||||
->content(':arrow_up: :package: '.trans('mail.Component_checkout_notification'))
|
||||
->from($botname)
|
||||
->to($channel)
|
||||
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
|
||||
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
|
||||
->fields($fields)
|
||||
->content($note);
|
||||
});
|
||||
}
|
||||
public function toMicrosoftTeams()
|
||||
{
|
||||
$target = $this->target;
|
||||
$admin = $this->admin;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
if(!Str::contains(Setting::getSettings()->webhook_endpoint, 'workflows')) {
|
||||
return MicrosoftTeamsMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->type('success')
|
||||
->addStartGroupToSection('activityTitle')
|
||||
->title(trans('mail.Component_checkout_notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
|
||||
->fact(trans('mail.Component_checkout_notification')." by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.assigned_to'), $target->present()->fullName())
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.Component_checkout_notification');
|
||||
$details = [
|
||||
trans('mail.assigned_to') => $target->present()->fullName(),
|
||||
trans('mail.item') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.Component_checkout_notification').' by' => $admin->present()->fullName(),
|
||||
trans('admin/consumables/general.remaining') => $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
|
||||
return array($message, $details);
|
||||
}
|
||||
public function toGoogleChat()
|
||||
{
|
||||
$target = $this->target;
|
||||
$item = $this->item;
|
||||
$note = $this->note;
|
||||
|
||||
return GoogleChatMessage::create()
|
||||
->to($this->settings->webhook_endpoint)
|
||||
->card(
|
||||
Card::create()
|
||||
->header(
|
||||
'<strong>'.trans('mail.Component_checkout_notification').'</strong>' ?: '',
|
||||
htmlspecialchars_decode($item->present()->name) ?: '',
|
||||
)
|
||||
->section(
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.assigned_to') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
)
|
||||
->onClick(route('api.assets.show', $target->id))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,15 @@ return [
|
||||
'Asset_Checkout_Notification' => 'Asset checked out',
|
||||
'Confirm_Accessory_Checkin' => 'Accessory checkin confirmation',
|
||||
'Confirm_Asset_Checkin' => 'Asset checkin confirmation',
|
||||
'Confirm_component_checkin' => 'Component checkin confirmation',
|
||||
'Confirm_accessory_delivery' => 'Accessory delivery confirmation',
|
||||
'Confirm_asset_delivery' => 'Asset delivery confirmation',
|
||||
'Confirm_consumable_delivery' => 'Consumable delivery confirmation',
|
||||
'Confirm_component_delivery' => 'Component delivery confirmation',
|
||||
'Confirm_license_delivery' => 'License delivery confirmation',
|
||||
'Consumable_checkout_notification' => 'Consumable checked out',
|
||||
'Component_checkout_notification' => 'Component checked out',
|
||||
'Component_checkin_notification' => 'Component checked in',
|
||||
'Days' => 'Days',
|
||||
'Expected_Checkin_Date' => 'An asset checked out to you is due to be checked back in on :date',
|
||||
'Expected_Checkin_Notification' => 'Reminder: :name checkin deadline approaching',
|
||||
|
||||
@@ -41,7 +41,31 @@
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@if ($component->requireAcceptance() || $component->getEula() || ($snipeSettings->webhook_endpoint!=''))
|
||||
<div class="form-group notification-callout">
|
||||
<div class="col-md-8 col-md-offset-3">
|
||||
<div class="callout callout-info">
|
||||
|
||||
@if ($component->category->require_acceptance=='1')
|
||||
<i class="far fa-envelope"></i>
|
||||
{{ trans('admin/categories/general.required_acceptance') }}
|
||||
<br>
|
||||
@endif
|
||||
|
||||
@if ($component->getEula())
|
||||
<i class="far fa-envelope"></i>
|
||||
{{ trans('admin/categories/general.required_eula') }}
|
||||
<br>
|
||||
@endif
|
||||
|
||||
@if ($snipeSettings->webhook_endpoint!='')
|
||||
<i class="fab fa-slack"></i>
|
||||
{{ trans('general.webhook_msg_note') }}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Note -->
|
||||
<div class="form-group{{ $errors->has('note') ? ' error' : '' }}">
|
||||
|
||||
25
resources/views/mail/markdown/checkin-component.blade.php
Normal file
25
resources/views/mail/markdown/checkin-component.blade.php
Normal file
@@ -0,0 +1,25 @@
|
||||
@component('mail::message')
|
||||
# {{ trans('mail.hello') }} {{ $target->assignedto->present()->fullName() }},
|
||||
|
||||
{{ trans('mail.the_following_item') }}
|
||||
|
||||
@component('mail::table')
|
||||
| | |
|
||||
| ------------- | ------------- |
|
||||
| **{{ trans('general.component') }}** | {{ $item->name }} |
|
||||
@if (isset($item->manufacturer))
|
||||
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
|
||||
@endif
|
||||
@if ($admin)
|
||||
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
|
||||
@endif
|
||||
@if ($note)
|
||||
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
|
||||
@endif
|
||||
@endcomponent
|
||||
|
||||
{{ trans('mail.best_regards') }}
|
||||
|
||||
{{ $snipeSettings->site_name }}
|
||||
|
||||
@endcomponent
|
||||
50
resources/views/mail/markdown/checkout-component.blade.php
Normal file
50
resources/views/mail/markdown/checkout-component.blade.php
Normal file
@@ -0,0 +1,50 @@
|
||||
@component('mail::message')
|
||||
# {{ trans('mail.hello') }} {{ $target->assignedto->present()->fullName() }},
|
||||
|
||||
{{ trans('mail.new_item_checked') }}
|
||||
|
||||
@component('mail::table')
|
||||
| | |
|
||||
| ------------- | ------------- |
|
||||
@if (isset($checkout_date))
|
||||
| **{{ trans('mail.checkout_date') }}** | {{ $checkout_date }} |
|
||||
@endif
|
||||
| **{{ trans('general.component') }}** | {{ $item->name }} |
|
||||
@if (isset($qty))
|
||||
| **{{ trans('general.qty') }}** | {{ $qty }} |
|
||||
@endif
|
||||
@if (isset($item->manufacturer))
|
||||
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
|
||||
@endif
|
||||
@if ($note)
|
||||
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
|
||||
@endif
|
||||
@if ($admin)
|
||||
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
|
||||
@endif
|
||||
@endcomponent
|
||||
|
||||
@if (($req_accept == 1) && ($eula!=''))
|
||||
{{ trans('mail.read_the_terms_and_click') }}
|
||||
@elseif (($req_accept == 1) && ($eula==''))
|
||||
{{ trans('mail.click_on_the_link_asset') }}
|
||||
@elseif (($req_accept == 0) && ($eula!=''))
|
||||
{{ trans('mail.read_the_terms') }}
|
||||
@endif
|
||||
|
||||
@if ($eula)
|
||||
@component('mail::panel')
|
||||
{!! $eula !!}
|
||||
@endcomponent
|
||||
@endif
|
||||
|
||||
@if ($req_accept == 1)
|
||||
**[✔ {{ trans('mail.i_have_read') }}]({{ $accept_url }})**
|
||||
@endif
|
||||
|
||||
|
||||
{{ trans('mail.best_regards') }}
|
||||
|
||||
{{ $snipeSettings->site_name }}
|
||||
|
||||
@endcomponent
|
||||
@@ -57,21 +57,42 @@
|
||||
@endif
|
||||
@elseif ($field->element=='checkbox')
|
||||
<!-- Checkboxes -->
|
||||
@php
|
||||
$fieldName = $field->db_column_name();
|
||||
$oldValues = old($fieldName);
|
||||
$defaultValues = array_map('trim', explode(',', $field->defaultValue($model->id)));
|
||||
$currentValues = isset($item) ? array_map('trim', explode(',', $item->{$fieldName})) : $defaultValues;
|
||||
|
||||
$selectedValues = is_array($oldValues) ? $oldValues : $currentValues;
|
||||
@endphp
|
||||
|
||||
@foreach ($field->formatFieldValuesAsArray() as $key => $value)
|
||||
<label class="form-control">
|
||||
<input type="checkbox"
|
||||
name="{{ $fieldName }}[]"
|
||||
value="{{ $key }}"
|
||||
{{ in_array($key, $selectedValues) ? 'checked' : '' }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
@endforeach
|
||||
@elseif ($field->element=='radio')
|
||||
@php
|
||||
$fieldName = $field->db_column_name();
|
||||
$oldValue = old($fieldName);
|
||||
$default = trim($field->defaultValue($model->id));
|
||||
$current = isset($item) ? trim($item->{$fieldName}) : $default;
|
||||
|
||||
$selectedValue = $oldValue !== null ? $oldValue : $current;
|
||||
@endphp
|
||||
@foreach ($field->formatFieldValuesAsArray() as $key => $value)
|
||||
<label class="form-control">
|
||||
<input type="checkbox" value="{{ $value }}" name="{{ $field->db_column_name() }}[]" {{ isset($item) ? (in_array($value, array_map('trim', explode(',', $item->{$field->db_column_name()}))) ? ' checked="checked"' : '') : (old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $field->defaultValue($model->id)))) ? ' checked="checked"' : '')) }}>
|
||||
<input type="radio"
|
||||
name="{{ $fieldName }}"
|
||||
value="{{ $key }}"
|
||||
{{ $selectedValue == $key ? 'checked' : '' }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
@endforeach
|
||||
@elseif ($field->element=='radio')
|
||||
@foreach ($field->formatFieldValuesAsArray() as $value)
|
||||
|
||||
<label class="form-control">
|
||||
<input type="radio" value="{{ $value }}" name="{{ $field->db_column_name() }}" {{ isset($item) ? ($item->{$field->db_column_name()} == $value ? ' checked="checked"' : '') : (old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($value, explode(', ', $field->defaultValue($model->id))) ? ' checked="checked"' : '')) }}>
|
||||
{{ $value }}
|
||||
</label>
|
||||
|
||||
@endforeach
|
||||
<button type="button"
|
||||
class="btn btn-default btn-xs clear-radio"
|
||||
data-target-name="{{ $field->db_column_name() }}">
|
||||
|
||||
@@ -52,7 +52,12 @@ Route::group(['middleware' => 'auth'], function () {
|
||||
[LabelsController::class, 'show']
|
||||
)->where('labelName', '.*')->name('labels.show');
|
||||
|
||||
Route::get('/test-email', function () {
|
||||
$mailable = new \App\Mail\CheckoutComponentMail(
|
||||
|
||||
);
|
||||
return $mailable->render(); // dumps HTML
|
||||
});
|
||||
/*
|
||||
* Manufacturers
|
||||
*/
|
||||
|
||||
@@ -152,6 +152,7 @@ Route::group(
|
||||
Route::delete('{asset}/showfile/{fileId}/delete',
|
||||
[AssetFilesController::class, 'destroy']
|
||||
)->name('delete/assetfile')->withTrashed();
|
||||
Route::get('hardware/bulkedit', [BulkAssetsController::class, 'bulkEditForm'])->name('hardware.bulkedit');
|
||||
|
||||
Route::post(
|
||||
'bulkedit',
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Tests\Feature\Notifications\Webhooks;
|
||||
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use App\Notifications\CheckinComponentNotification;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
@@ -96,6 +97,31 @@ class SlackNotificationsUponCheckinTest extends TestCase
|
||||
|
||||
$this->assertNoSlackNotificationSent(CheckinAssetNotification::class);
|
||||
}
|
||||
#[DataProvider('assetCheckInTargets')]
|
||||
public function testComponentCheckinSendsSlackNotificationWhenSettingEnabled($checkoutTarget)
|
||||
{
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
$this->fireCheckInEvent(
|
||||
Component::factory()->create(),
|
||||
$checkoutTarget(),
|
||||
);
|
||||
|
||||
$this->assertSlackNotificationSent(CheckinComponentNotification::class);
|
||||
}
|
||||
|
||||
#[DataProvider('assetCheckInTargets')]
|
||||
public function testComponentCheckinDoesNotSendSlackNotificationWhenSettingDisabled($checkoutTarget)
|
||||
{
|
||||
$this->settings->disableSlackWebhook();
|
||||
|
||||
$this->fireCheckInEvent(
|
||||
Component::factory()->create(),
|
||||
$checkoutTarget(),
|
||||
);
|
||||
|
||||
$this->assertNoSlackNotificationSent(CheckinComponentNotification::class);
|
||||
}
|
||||
|
||||
public function testSlackNotificationIsStillSentWhenCategoryEmailIsNotSetToSendEmails()
|
||||
{
|
||||
@@ -118,18 +144,6 @@ class SlackNotificationsUponCheckinTest extends TestCase
|
||||
$this->assertSlackNotificationSent(CheckinAssetNotification::class);
|
||||
}
|
||||
|
||||
public function testComponentCheckinDoesNotSendSlackNotification()
|
||||
{
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
$this->fireCheckInEvent(
|
||||
Component::factory()->create(),
|
||||
Asset::factory()->laptopMbp()->create(),
|
||||
);
|
||||
|
||||
Notification::assertNothingSent();
|
||||
}
|
||||
|
||||
#[DataProvider('licenseCheckInTargets')]
|
||||
public function testLicenseCheckinSendsSlackNotificationWhenSettingEnabled($checkoutTarget)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace Tests\Feature\Notifications\Webhooks;
|
||||
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use App\Notifications\CheckoutComponentNotification;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
@@ -30,12 +32,13 @@ class SlackNotificationsUponCheckoutTest extends TestCase
|
||||
parent::setUp();
|
||||
|
||||
Notification::fake();
|
||||
Mail::fake();
|
||||
}
|
||||
|
||||
public static function assetCheckoutTargets(): array
|
||||
{
|
||||
return [
|
||||
'Asset checked out to user' => [fn() => User::factory()->create()],
|
||||
'Asset checked out to user' => [fn() => User::factory()->create(['email' => null])],
|
||||
'Asset checked out to asset' => [fn() => Asset::factory()->laptopMbp()->create()],
|
||||
'Asset checked out to location' => [fn() => Location::factory()->create()],
|
||||
];
|
||||
@@ -44,7 +47,7 @@ class SlackNotificationsUponCheckoutTest extends TestCase
|
||||
public static function licenseCheckoutTargets(): array
|
||||
{
|
||||
return [
|
||||
'License checked out to user' => [fn() => User::factory()->create()],
|
||||
'License checked out to user' => [fn() => User::factory()->create(['email' => null])],
|
||||
'License checked out to asset' => [fn() => Asset::factory()->laptopMbp()->create()],
|
||||
];
|
||||
}
|
||||
@@ -98,7 +101,41 @@ class SlackNotificationsUponCheckoutTest extends TestCase
|
||||
|
||||
$this->assertNoSlackNotificationSent(CheckoutAssetNotification::class);
|
||||
}
|
||||
#[DataProvider('assetCheckoutTargets')]
|
||||
public function testComponentCheckoutSendsSlackNotificationWhenSettingEnabled($checkoutTarget)
|
||||
{
|
||||
$this->settings->enableSlackWebhook();
|
||||
$component = Component::factory()->create([
|
||||
'category_id' => Category::factory()->create([
|
||||
'require_acceptance' => false,
|
||||
'eula_text' => null,
|
||||
]),
|
||||
]);
|
||||
$this->fireCheckOutEvent(
|
||||
$component,
|
||||
$checkoutTarget(),
|
||||
);
|
||||
|
||||
$this->assertSlackNotificationSent(CheckoutComponentNotification::class);
|
||||
}
|
||||
|
||||
#[DataProvider('assetCheckoutTargets')]
|
||||
public function testComponentCheckoutDoesNotSendSlackNotificationWhenSettingDisabled($checkoutTarget)
|
||||
{
|
||||
$this->settings->disableSlackWebhook();
|
||||
$component = Component::factory()->create([
|
||||
'category_id' => Category::factory()->create([
|
||||
'require_acceptance' => false,
|
||||
'eula_text' => null,
|
||||
]),
|
||||
]);
|
||||
$this->fireCheckOutEvent(
|
||||
$component,
|
||||
$checkoutTarget(),
|
||||
);
|
||||
|
||||
$this->assertNoSlackNotificationSent(CheckoutComponentNotification::class);
|
||||
}
|
||||
public function testSlackNotificationIsStillSentWhenCategoryEmailIsNotSetToSendEmails()
|
||||
{
|
||||
$this->settings->enableSlackWebhook();
|
||||
@@ -120,18 +157,6 @@ class SlackNotificationsUponCheckoutTest extends TestCase
|
||||
$this->assertSlackNotificationSent(CheckoutAssetNotification::class);
|
||||
}
|
||||
|
||||
public function testComponentCheckoutDoesNotSendSlackNotification()
|
||||
{
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
$this->fireCheckOutEvent(
|
||||
Component::factory()->create(),
|
||||
Asset::factory()->laptopMbp()->create(),
|
||||
);
|
||||
|
||||
Notification::assertNothingSent();
|
||||
}
|
||||
|
||||
public function testConsumableCheckoutSendsSlackNotificationWhenSettingEnabled()
|
||||
{
|
||||
$this->settings->enableSlackWebhook();
|
||||
|
||||
Reference in New Issue
Block a user