- Implemented `EnumMorphsToOptionsContract` interface to enable enums with options and labels for dropdowns. - Created `SamlNameIdFormatEnum` and `SamlNameIdSourceEnum` for standardized SAML NameID configuration. - Added reusable `SAML Configuration` Blade component for easier integration into connected app forms. - Enabled custom SAML Attribute mapping with dynamic add/remove functionality and validation. - Improved `SamlIdpController` to enforce ACS URL matching and user authorization checks. - Refactored SAML-related tests and added scenarios for role-based SAML access and custom configurations.
107 lines
3.3 KiB
PHP
107 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Livewire\Forms;
|
|
|
|
use App\Data\ConnectedApp\ConnectedAppData;
|
|
use App\Enums\ConnectionProtocolEnum;
|
|
use App\Models\ConnectionProtocol;
|
|
use App\Services\ConnectedAppService;
|
|
use Livewire\Form;
|
|
|
|
class StoreConnectedAppFrom extends Form
|
|
{
|
|
public string $name = '';
|
|
|
|
public int $providerId = 0;
|
|
|
|
public int $protocolId = 0;
|
|
|
|
public int $statusId = 0;
|
|
|
|
public string $samlEntityId = '';
|
|
|
|
public string $samlAcsUrl = '';
|
|
|
|
public string $samlNameIdFormat = 'persistent';
|
|
|
|
public string $samlNameIdSource = 'immutable_id';
|
|
|
|
public array $samlAttributes = [];
|
|
|
|
protected ConnectedAppService $service;
|
|
|
|
public function boot(ConnectedAppService $service): void
|
|
{
|
|
$this->service = $service;
|
|
}
|
|
|
|
/**
|
|
* Get the dynamic validation rules for the form.
|
|
*
|
|
* @return array<string, string>
|
|
*/
|
|
public function rules(): array
|
|
{
|
|
$rules = [
|
|
'name' => 'required|string|max:255|min:3',
|
|
'providerId' => 'required|numeric|min:1|exists:connection_providers,id',
|
|
'protocolId' => 'required|numeric|min:1|exists:connection_protocols,id',
|
|
'statusId' => 'required|numeric|min:1|exists:connection_statuses,id',
|
|
];
|
|
|
|
$protocol = ConnectionProtocol::query()->find($this->protocolId);
|
|
if ($protocol && ConnectionProtocolEnum::SAML->value === mb_strtolower($protocol->name)) {
|
|
$rules['samlEntityId'] = 'required|string|min:3';
|
|
$rules['samlAcsUrl'] = 'required|url';
|
|
$rules['samlNameIdFormat'] = 'required|string|in:persistent,emailAddress,transient,unspecified';
|
|
$rules['samlNameIdSource'] = 'required|string|in:immutable_id,email,id';
|
|
$rules['samlAttributes'] = 'array';
|
|
$rules['samlAttributes.*.saml_name'] = 'required|string|min:1';
|
|
$rules['samlAttributes.*.user_field'] = 'required|string|in:email,name,immutable_id,id';
|
|
}
|
|
|
|
return $rules;
|
|
}
|
|
|
|
/**
|
|
* This sets the form to edit mode, after fetching the connected app of
|
|
* the given id.
|
|
*/
|
|
public function set(ConnectedAppData $data): void
|
|
{
|
|
$this->name = $data->name;
|
|
$this->protocolId = $data->protocolId;
|
|
$this->providerId = $data->providerId;
|
|
$this->statusId = $data->statusId;
|
|
$this->samlEntityId = $data->settings['saml']['entity_id'] ?? '';
|
|
$this->samlAcsUrl = $data->settings['saml']['acs_url'] ?? '';
|
|
$this->samlNameIdFormat = $data->settings['saml']['nameid_format'] ?? 'persistent';
|
|
$this->samlNameIdSource = $data->settings['saml']['nameid_source'] ?? 'immutable_id';
|
|
|
|
$this->samlAttributes = [];
|
|
$attributes = $data->settings['saml']['attributes'] ?? [];
|
|
foreach ($attributes as $samlName => $userField) {
|
|
$this->samlAttributes[] = [
|
|
'saml_name' => $samlName,
|
|
'user_field' => $userField,
|
|
];
|
|
}
|
|
}
|
|
|
|
public function addSamlAttribute(): void
|
|
{
|
|
$this->samlAttributes[] = [
|
|
'saml_name' => '',
|
|
'user_field' => 'email',
|
|
];
|
|
}
|
|
|
|
public function removeSamlAttribute(int $index): void
|
|
{
|
|
unset($this->samlAttributes[$index]);
|
|
$this->samlAttributes = array_values($this->samlAttributes);
|
|
}
|
|
}
|