mirror of
https://github.com/snipe/snipe-it.git
synced 2026-08-18 03:06:23 +00:00
Normalize HTTP responses for external services
Change various hooks to better determine HTTP status codes Got webhooks to test OK in Slack, at least
This commit is contained in:
@ -2216,4 +2216,41 @@ class Helper
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force equal timing between 'success' and 'failure' to not expose open ports
|
||||
*/
|
||||
public static function EqualTiming(int $seconds, callable $function)
|
||||
{
|
||||
$start = microtime(true);
|
||||
$thrown_exception = null;
|
||||
$result = null;
|
||||
try {
|
||||
$result = $function();
|
||||
if (is_bool($result)) {
|
||||
if ($result) {
|
||||
return; //instant return on success
|
||||
}
|
||||
} //Fall-through on failure - $result is false so the next 'if' will not fire
|
||||
if ($result && $result->getStatusCode() == 200) {
|
||||
//succesful responses should return 'fast'
|
||||
return $result;
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$thrown_exception = $exception;
|
||||
}
|
||||
// on *any* transaction(?), make sure we don't do a 'fast fail' -
|
||||
// it needs to take $seconds seconds.
|
||||
$end = microtime(true);
|
||||
$duration = $end - $start;
|
||||
$remaining = $seconds - $duration;
|
||||
if ($remaining > 0) {
|
||||
sleep((int) $remaining);
|
||||
}
|
||||
if ($thrown_exception) {
|
||||
throw $thrown_exception;
|
||||
}
|
||||
return $result;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,13 +29,13 @@ class SettingsController extends Controller
|
||||
|
||||
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
|
||||
}
|
||||
return Helper::EqualTiming(5, function () {
|
||||
|
||||
Log::debug('Preparing to test LDAP connection');
|
||||
Log::debug('Preparing to test LDAP connection');
|
||||
|
||||
$message = []; // where we collect together test messages
|
||||
try {
|
||||
$connection = Ldap::connectToLdap();
|
||||
$message = []; // where we collect together test messages
|
||||
try {
|
||||
$connection = Ldap::connectToLdap();
|
||||
$message['bind'] = ['message' => 'Successfully bound to LDAP server.'];
|
||||
Log::debug('attempting to bind to LDAP for LDAP test');
|
||||
Ldap::bindAdminToLdap($connection);
|
||||
@ -52,8 +52,7 @@ class SettingsController extends Controller
|
||||
return is_int($key);
|
||||
})->slice(0, 10)->map(function ($item) {
|
||||
$mapped = Ldap::parseAndMapLdapAttributes($item);
|
||||
|
||||
return (object) array_map(fn ($value) => $value === '' ? null : $value, $mapped);
|
||||
return (object) array_map(fn($value) => $value === '' ? null : $value, $mapped);
|
||||
});
|
||||
if ($users->count() > 0) {
|
||||
// `fields` is the ordered internal_key => translated
|
||||
@ -63,7 +62,7 @@ class SettingsController extends Controller
|
||||
// consistent as attributeMap() grows.
|
||||
$labels = Ldap::attributeLabels();
|
||||
$fields = collect(array_keys(Ldap::parseAndMapLdapAttributes([])))
|
||||
->mapWithKeys(fn ($key) => [$key => $labels[$key] ?? $key])
|
||||
->mapWithKeys(fn($key) => [$key => $labels[$key] ?? $key])
|
||||
->all();
|
||||
$message['user_sync'] = [
|
||||
'fields' => $fields,
|
||||
@ -79,18 +78,11 @@ class SettingsController extends Controller
|
||||
|
||||
return response()->json($message, 200);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug('Bind failed');
|
||||
Log::debug('Exception was: '.$e->getMessage());
|
||||
Log::debug('Connection failed but we cannot debug it any further on our end.');
|
||||
|
||||
return response()->json(['message' => $e->getMessage()], 400);
|
||||
// return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::debug('Connection failed but we cannot debug it any further on our end.');
|
||||
|
||||
return response()->json(['message' => $e->getMessage()], 400);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public function ldaptestlogin(Request $request): JsonResponse
|
||||
|
||||
@ -8,6 +8,7 @@ use App\Rules\ExternalUrl;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Component;
|
||||
@ -41,10 +42,14 @@ class SlackSettingsForm extends Component
|
||||
|
||||
public $save_button;
|
||||
|
||||
public $webhook_test;
|
||||
|
||||
public $webhook_endpoint_rules;
|
||||
|
||||
public ?string $warning = null;
|
||||
|
||||
public ?string $success = null;
|
||||
|
||||
public ?string $error = null;
|
||||
|
||||
protected function rules(): array
|
||||
{
|
||||
return [
|
||||
@ -82,59 +87,56 @@ class SlackSettingsForm extends Component
|
||||
'icon' => 'fab fa-slack',
|
||||
'placeholder' => 'https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXX',
|
||||
'link' => 'https://api.slack.com/messaging/webhooks',
|
||||
'test' => 'testWebhook',
|
||||
],
|
||||
'general' => [
|
||||
'name' => trans('admin/settings/general.general_webhook'),
|
||||
'icon' => 'fab fa-hashtag',
|
||||
'placeholder' => trans('general.url'),
|
||||
'link' => '',
|
||||
'test' => 'testWebhook',
|
||||
],
|
||||
'google' => [
|
||||
'name' => trans('admin/settings/general.google_workspaces'),
|
||||
'icon' => 'fa-brands fa-google',
|
||||
'placeholder' => 'https://chat.googleapis.com/v1/spaces/xxxxxxxx/messages?key=xxxxxx',
|
||||
'link' => 'https://developers.google.com/chat/how-tos/webhooks#register_the_incoming_webhook',
|
||||
'test' => 'googleWebhookTest',
|
||||
],
|
||||
'microsoft' => [
|
||||
'name' => trans('admin/settings/general.ms_teams'),
|
||||
'icon' => 'fa-brands fa-microsoft',
|
||||
'placeholder' => 'https://abcd.webhook.office.com/webhookb2/XXXXXXX',
|
||||
'link' => 'https://support.microsoft.com/en-us/office/create-incoming-webhooks-with-workflows-for-microsoft-teams-8ae491c7-0394-4861-ba59-055e33f75498',
|
||||
'test' => 'msTeamTestWebhook',
|
||||
],
|
||||
];
|
||||
|
||||
$this->setting = Setting::getSettings();
|
||||
$this->save_button = trans('general.save');
|
||||
$this->webhook_selected = ($this->setting->webhook_selected !== '') ? $this->setting->webhook_selected : 'slack';
|
||||
$this->webhook_name = $this->webhook_text[$this->setting->webhook_selected]['name'] ?? $this->webhook_text['slack']['name'];
|
||||
$this->webhook_icon = $this->webhook_text[$this->setting->webhook_selected]['icon'] ?? $this->webhook_text['slack']['icon'];
|
||||
$this->webhook_placeholder = $this->webhook_text[$this->setting->webhook_selected]['placeholder'] ?? $this->webhook_text['slack']['placeholder'];
|
||||
$this->webhook_link = $this->webhook_text[$this->setting->webhook_selected]['link'] ?? $this->webhook_text['slack']['link'];
|
||||
$this->webhook_test = $this->webhook_text[$this->setting->webhook_selected]['test'] ?? $this->webhook_text['slack']['test'];
|
||||
if (!$this->webhook_selected) {
|
||||
$this->webhook_selected = 'slack';
|
||||
}
|
||||
|
||||
|
||||
$this->webhook_options = $this->setting->webhook_selected ? $this->setting->webhook_selected : 'slack';
|
||||
|
||||
|
||||
$this->updatedWebhookSelected();
|
||||
$this->webhook_endpoint = $this->setting->webhook_endpoint;
|
||||
$this->webhook_channel = $this->setting->webhook_channel;
|
||||
$this->webhook_botname = $this->setting->webhook_botname;
|
||||
$this->webhook_options = $this->setting->webhook_selected;
|
||||
$this->teams_webhook_deprecated = ! Str::contains($this->webhook_endpoint, 'workflows');
|
||||
if ($this->webhook_selected === 'microsoft' || $this->webhook_selected === 'google') {
|
||||
$this->webhook_channel = '#NA';
|
||||
}
|
||||
$this->teams_webhook_deprecated = !Str::contains($this->webhook_endpoint, 'workflows'); // consider moving this to webhook_link updated? (updatedWebhookLink?)
|
||||
|
||||
if ($this->setting->webhook_endpoint != null && $this->setting->webhook_channel != null) {
|
||||
$this->isDisabled = '';
|
||||
}
|
||||
if ($this->webhook_selected === 'microsoft' && $this->teams_webhook_deprecated) {
|
||||
session()->flash('warning', trans('admin/settings/message.webhook.ms_teams_deprecation'));
|
||||
if ($this->webhook_selected === 'microsoft' && $this->teams_webhook_deprecated) { //since this is URL-aware, maybe also move this?
|
||||
$this->warning = trans('admin/settings/message.webhook.ms_teams_deprecation');
|
||||
}
|
||||
}
|
||||
|
||||
public function updated($field)
|
||||
{
|
||||
|
||||
//anything changes; then clear the succcess message (and error message)
|
||||
$this->success = null;
|
||||
$this->error = null;
|
||||
$this->validateOnly($field);
|
||||
|
||||
}
|
||||
@ -144,10 +146,9 @@ class SlackSettingsForm extends Component
|
||||
$this->webhook_name = $this->webhook_text[$this->webhook_selected]['name'];
|
||||
$this->webhook_icon = $this->webhook_text[$this->webhook_selected]['icon'];
|
||||
$this->webhook_placeholder = $this->webhook_text[$this->webhook_selected]['placeholder'];
|
||||
$this->webhook_endpoint = null;
|
||||
$this->webhook_endpoint = null; // TODO - do we really want to blank this?
|
||||
$this->webhook_link = $this->webhook_text[$this->webhook_selected]['link'];
|
||||
$this->webhook_test = $this->webhook_text[$this->webhook_selected]['test'];
|
||||
if ($this->webhook_selected != 'slack') {
|
||||
if ($this->webhook_selected != 'slack') { // TODO: hrm. Wouldn't we want to test all of them? Or at least some of them? Maybe not "generic webhook"?
|
||||
$this->isDisabled = '';
|
||||
$this->save_button = trans('general.save');
|
||||
}
|
||||
@ -158,76 +159,25 @@ class SlackSettingsForm extends Component
|
||||
|
||||
public function updatedwebhookEndpoint()
|
||||
{
|
||||
$this->teams_webhook_deprecated = ! Str::contains($this->webhook_endpoint, 'workflows');
|
||||
}
|
||||
|
||||
private function isButtonDisabled()
|
||||
{
|
||||
if (empty($this->webhook_endpoint)) {
|
||||
$this->isDisabled = 'disabled';
|
||||
$this->save_button = trans('admin/settings/general.webhook_presave');
|
||||
}
|
||||
if (empty($this->webhook_channel)) {
|
||||
$this->isDisabled = 'disabled';
|
||||
$this->save_button = trans('admin/settings/general.webhook_presave');
|
||||
}
|
||||
$this->teams_webhook_deprecated = !Str::contains($this->webhook_endpoint, 'workflows');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$this->isButtonDisabled();
|
||||
if (empty($this->webhook_endpoint) || empty($this->webhook_channel)) {
|
||||
$this->isDisabled = 'disabled';
|
||||
$this->save_button = trans('admin/settings/general.webhook_presave');
|
||||
}
|
||||
|
||||
return view('livewire.slack-settings-form');
|
||||
|
||||
}
|
||||
|
||||
public function testWebhook()
|
||||
{
|
||||
if ($fail = $this->guardWebhookEndpoint()) {
|
||||
return $fail;
|
||||
}
|
||||
|
||||
$webhook = new Client([
|
||||
'base_url' => e($this->webhook_endpoint),
|
||||
'defaults' => [
|
||||
'exceptions' => false,
|
||||
],
|
||||
'allow_redirects' => false,
|
||||
]);
|
||||
|
||||
$payload = json_encode(
|
||||
[
|
||||
'channel' => e($this->webhook_channel),
|
||||
'text' => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
|
||||
'username' => e($this->webhook_botname),
|
||||
'icon_emoji' => ':heart:',
|
||||
|
||||
]);
|
||||
|
||||
try {
|
||||
$test = $webhook->post($this->webhook_endpoint, ['body' => $payload, 'headers' => ['Content-Type' => 'application/json']]);
|
||||
|
||||
if (($test->getStatusCode() == 302) || ($test->getStatusCode() == 301)) {
|
||||
return session()->flash('error', trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]));
|
||||
}
|
||||
$this->isDisabled = '';
|
||||
$this->save_button = trans('general.save');
|
||||
|
||||
return session()->flash('success', trans('admin/settings/message.webhook.success', ['webhook_name' => $this->webhook_name]));
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return $this->handleWebhookFailure($e);
|
||||
}
|
||||
|
||||
return session()->flash('error', trans('admin/settings/message.webhook.error_misc'));
|
||||
|
||||
}
|
||||
|
||||
public function clearSettings()
|
||||
{
|
||||
|
||||
if (Helper::isDemoMode()) {
|
||||
session()->flash('error', trans('general.feature_disabled'));
|
||||
$this->error = trans('general.feature_disabled');
|
||||
} else {
|
||||
$this->webhook_endpoint = '';
|
||||
$this->webhook_channel = '';
|
||||
@ -238,14 +188,14 @@ class SlackSettingsForm extends Component
|
||||
|
||||
$this->setting->save();
|
||||
|
||||
session()->flash('success', trans('admin/settings/message.update.success'));
|
||||
$this->success = trans('admin/settings/message.update.success');
|
||||
}
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
if (Helper::isDemoMode()) {
|
||||
session()->flash('error', trans('general.feature_disabled'));
|
||||
$this->error = trans('general.feature_disabled');
|
||||
} else {
|
||||
$this->validate();
|
||||
|
||||
@ -256,142 +206,114 @@ class SlackSettingsForm extends Component
|
||||
|
||||
$this->setting->save();
|
||||
|
||||
session()->flash('success', trans('admin/settings/message.update.success'));
|
||||
$this->success = trans('admin/settings/message.update.success');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function googleWebhookTest()
|
||||
public function universalWebhookTest()
|
||||
{
|
||||
if ($fail = $this->guardWebhookEndpoint()) {
|
||||
return $fail;
|
||||
}
|
||||
$executed = RateLimiter::attempt(
|
||||
key: 'test-connection:' . auth()->id(),
|
||||
maxAttempts: 5,
|
||||
decaySeconds: 60,
|
||||
callback: function () {
|
||||
$validator = Validator::make(
|
||||
['webhook_endpoint' => $this->webhook_endpoint],
|
||||
['webhook_endpoint' => ['required', 'url', new ExternalUrl]],
|
||||
);
|
||||
|
||||
$payload = [
|
||||
'text' => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
|
||||
];
|
||||
if ($validator->fails()) {
|
||||
$this->isDisabled = 'disabled';
|
||||
$this->save_button = trans('admin/settings/general.webhook_presave');
|
||||
|
||||
try {
|
||||
$response = Http::withHeaders([
|
||||
'content-type' => 'application/json',
|
||||
])->withOptions(['allow_redirects' => false])
|
||||
->post($this->webhook_endpoint, $payload)
|
||||
->throw();
|
||||
$this->error = $validator->errors()->first('webhook_endpoint');
|
||||
return;
|
||||
}
|
||||
$this->error = '';
|
||||
$this->success = '';
|
||||
|
||||
if (($response->getStatusCode() == 302) || ($response->getStatusCode() == 301)) {
|
||||
return session()->flash('error', trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]));
|
||||
}
|
||||
|
||||
$this->isDisabled = '';
|
||||
$this->save_button = trans('general.save');
|
||||
|
||||
return session()->flash('success', trans('admin/settings/message.webhook.success', ['webhook_name' => $this->webhook_name]));
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return $this->handleWebhookFailure($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function msTeamTestWebhook()
|
||||
{
|
||||
if ($fail = $this->guardWebhookEndpoint()) {
|
||||
return $fail;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if ($this->teams_webhook_deprecated) {
|
||||
// will use the deprecated webhook format
|
||||
$payload =
|
||||
[
|
||||
$payload = match ($this->webhook_selected) {
|
||||
'slack', 'general' => [
|
||||
'channel' => e($this->webhook_channel),
|
||||
'text' => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
|
||||
'username' => e($this->webhook_botname),
|
||||
'icon_emoji' => ':heart:',
|
||||
],
|
||||
'google' => [
|
||||
'text' => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
|
||||
],
|
||||
'microsoft' => [
|
||||
'@type' => 'MessageCard',
|
||||
'@context' => 'http://schema.org/extensions',
|
||||
'summary' => trans('mail.snipe_webhook_summary'),
|
||||
'title' => trans('mail.snipe_webhook_test'),
|
||||
'text' => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
|
||||
];
|
||||
$response = Http::withHeaders([
|
||||
'content-type' => 'application/json',
|
||||
])->withOptions(['allow_redirects' => false])
|
||||
->post($this->webhook_endpoint, $payload)
|
||||
->throw();
|
||||
} else {
|
||||
$notification = new TeamsNotification($this->webhook_endpoint);
|
||||
$message = trans('general.webhook_test_msg', ['app' => $this->webhook_name]);
|
||||
$notification->success()->sendMessage($message);
|
||||
],
|
||||
default => throw new \Exception("Unknown provider")
|
||||
};
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'content-type' => 'application/json',
|
||||
])->withOptions(['allow_redirects' => false])
|
||||
->post($this->webhook_endpoint);
|
||||
}
|
||||
$status_code = null;
|
||||
|
||||
if (($response->getStatusCode() == 302) || ($response->getStatusCode() == 301)) {
|
||||
return session()->flash('error', trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]));
|
||||
}
|
||||
$this->isDisabled = '';
|
||||
$this->save_button = trans('general.save');
|
||||
try {
|
||||
if ($this->webhook_selected == "microsoft" && !$this->teams_webhook_deprecated) {
|
||||
//new-fangled webhook - use package
|
||||
$notification = new TeamsNotification($this->webhook_endpoint);
|
||||
$message = trans('general.webhook_test_msg', ['app' => $this->webhook_name]);
|
||||
$status_code = $notification->success()->sendMessage($message);
|
||||
} else {
|
||||
$response = Http::withHeaders([
|
||||
'content-type' => 'application/json',
|
||||
])->withOptions(['allow_redirects' => false])
|
||||
->post($this->webhook_endpoint, $payload)/*->throw()*/
|
||||
;
|
||||
$status_code = $response->getStatusCode();
|
||||
}
|
||||
|
||||
return session()->flash('success', trans('admin/settings/message.webhook.success', ['webhook_name' => $this->webhook_name]));
|
||||
if ($status_code >= 300 && $status_code < 400) {
|
||||
//these, still, might happen. It seems like allow_redirects being false just doesn't follow them, it doesn't cause an Exception on them.
|
||||
$this->error = trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]);
|
||||
//TODO: one possibliity here is to re-throw so that everything goes back through the exception handler?
|
||||
} elseif ($status_code >= 400 && $status_code < 500) {
|
||||
//this _shouldn't_ happen because the "->throw()" should catch it
|
||||
$this->error = trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]);
|
||||
} elseif ($status_code >= 500) {
|
||||
//this _shouldn't_ happen because the "->throw()" should catch it
|
||||
$this->error = trans('admin/settings/message.webhook.error_server');
|
||||
} elseif ($status_code >= 200 && $status_code < 300) {
|
||||
$this->isDisabled = '';
|
||||
$this->save_button = trans('general.save');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return $this->handleWebhookFailure($e);
|
||||
}
|
||||
$this->success = trans('admin/settings/message.webhook.success', ['webhook_name' => $this->webhook_name]);
|
||||
return true; // This is just for EqualTiming to use; this method on this controller doesn't actually return anything
|
||||
} else {
|
||||
throw new \Exception(trans('admin/settings/message.webhook.error_misc'));
|
||||
}
|
||||
|
||||
return session()->flash('error', trans('admin/settings/message.webhook.error_misc'));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::warning('Webhook test failed', [
|
||||
'endpoint' => $this->webhook_endpoint,
|
||||
'app' => $this->webhook_name,
|
||||
'exception' => $e::class,
|
||||
'message' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
]);
|
||||
|
||||
/**
|
||||
* Re-validate the currently-entered endpoint immediately before an
|
||||
* outbound request. This is defense-in-depth on top of the save-time
|
||||
* ExternalUrl rule: it stops a super-admin from typing an internal
|
||||
* URL, clicking Test, and having the server dial it before the value
|
||||
* is ever persisted. Returns a flash-response on failure, null on pass.
|
||||
*/
|
||||
private function guardWebhookEndpoint()
|
||||
{
|
||||
$validator = Validator::make(
|
||||
['webhook_endpoint' => $this->webhook_endpoint],
|
||||
['webhook_endpoint' => ['required', 'url', new ExternalUrl]],
|
||||
$this->isDisabled = 'disabled';
|
||||
$this->save_button = trans('admin/settings/general.webhook_presave');
|
||||
|
||||
$this->error = trans('admin/settings/message.webhook.error', [
|
||||
'error_message' => $e->getMessage(),
|
||||
'app' => $this->webhook_name,
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if ($validator->fails()) {
|
||||
$this->isDisabled = 'disabled';
|
||||
$this->save_button = trans('admin/settings/general.webhook_presave');
|
||||
|
||||
return session()->flash('error', $validator->errors()->first('webhook_endpoint'));
|
||||
if (!$executed) {
|
||||
$this->addError('connection', trans('admin/settings/general.rate_limited'));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uniform failure path for outbound webhook tests. The exception message
|
||||
* used to be a port-scanning oracle back when the endpoint field accepted
|
||||
* internal URLs; now that the ExternalUrl rule rejects those before we
|
||||
* ever dial anything, the connect-level error can only describe an
|
||||
* external host the admin explicitly typed, so we surface it back into
|
||||
* the flash. Full exception context still lands in the log for audit
|
||||
* and for cases where the flash message is too short to be useful (SSL
|
||||
* chain problems, proxy failures, etc.).
|
||||
*/
|
||||
private function handleWebhookFailure(\Throwable $e)
|
||||
{
|
||||
Log::warning('Webhook test failed', [
|
||||
'endpoint' => $this->webhook_endpoint,
|
||||
'app' => $this->webhook_name,
|
||||
'exception' => $e::class,
|
||||
'message' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
]);
|
||||
|
||||
$this->isDisabled = 'disabled';
|
||||
$this->save_button = trans('admin/settings/general.webhook_presave');
|
||||
|
||||
return session()->flash('error', trans('admin/settings/message.webhook.error', [
|
||||
'error_message' => $e->getMessage(),
|
||||
'app' => $this->webhook_name,
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,14 +13,11 @@
|
||||
@section('content')
|
||||
|
||||
<div><!-- livewire div - do not remove -->
|
||||
<form class="form-horizontal" role="form" wire:submit="submit">
|
||||
<form class="form-horizontal" role="form" wire:submit.prevent="submit">
|
||||
{{csrf_field()}}
|
||||
@if (session()->has('warning'))
|
||||
@if ($warning)
|
||||
<x-alert type="warning">
|
||||
{!! session('warning') !!}
|
||||
@php
|
||||
session()->forget('warning'); // Clear the session flash immediately
|
||||
@endphp
|
||||
{!! $warning !!}
|
||||
</x-alert>
|
||||
@endif
|
||||
<div class="row">
|
||||
@ -47,17 +44,16 @@
|
||||
|
||||
<div class="col-md-12" style="border-top: 0px;">
|
||||
|
||||
@if(session()->has('success'))
|
||||
@if($success)
|
||||
<x-alert type="success">
|
||||
{{session('success')}}
|
||||
{{$success}}
|
||||
</x-alert>
|
||||
@endif
|
||||
@if(session()->has('error'))
|
||||
@if($error)
|
||||
<x-alert type="danger">
|
||||
{{session('error')}}
|
||||
{{$error}}
|
||||
</x-alert>
|
||||
@endif
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-2">
|
||||
<label for="webhook_selected">
|
||||
@ -140,7 +136,7 @@
|
||||
@if($webhook_endpoint != null && $webhook_channel != null)
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-2 col-md-9">
|
||||
<a href="#" wire:click.prevent="{{$webhook_test}}"
|
||||
<a href="#" wire:click.prevent="universalWebhookTest"
|
||||
class="btn btn-default btn-sm pull-left">
|
||||
<i class="{{$webhook_icon}}" aria-hidden="true"></i>
|
||||
{!! trans('admin/settings/general.webhook_test',['app' => ucwords($webhook_selected) ]) !!}
|
||||
|
||||
@ -976,7 +976,7 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
Api\SettingsController::class,
|
||||
'ldaptest',
|
||||
]
|
||||
)->name('api.settings.ldaptest');
|
||||
)->middleware('throttle:5,1')->name('api.settings.ldaptest');
|
||||
|
||||
Route::post('purge_barcodes',
|
||||
[
|
||||
@ -997,7 +997,7 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'api-throttle:api']], fu
|
||||
Api\SettingsController::class,
|
||||
'ldaptestlogin',
|
||||
]
|
||||
)->name('api.settings.ldaptestlogin');
|
||||
)->middleware('throttle:5,1')->name('api.settings.ldaptestlogin');
|
||||
|
||||
Route::post('mailtest',
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user