FestinHegre/vendor/symfony/security-bundle/Resources/views/Collector/security.html.twig

507 lines
26 KiB
Twig
Raw Normal View History

2024-09-26 17:26:04 +02:00
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
{% block page_title 'Security' %}
{% block head %}
{{ parent() }}
<style>
#collector-content .decision-log .voter_result td {
border-top-width: 1px;
border-bottom-width: 0;
padding-bottom: 0;
}
#collector-content .decision-log .voter_details td {
border-top-width: 0;
border-bottom-width: 1px;
padding-bottom: 0;
}
#collector-content .decision-log .voter_details table {
border: 0;
margin: 0;
box-shadow: unset;
}
#collector-content .decision-log .voter_details table td {
border: 0;
padding: 0 0 8px 0;
}
#collector-content .authenticators .badge {
color: var(--white);
display: inline-block;
text-align: center;
}
#collector-content .authenticators .badge.badge-resolved {
background-color: var(--green-500);
}
#collector-content .authenticators .badge.badge-not_resolved {
background-color: var(--yellow-500);
}
#collector-content .authenticators svg[data-icon-name="icon-tabler-check"] {
color: var(--green-500);
}
#collector-content .authenticators svg[data-icon-name="icon-tabler-x"] {
color: var(--red-500);
}
</style>
{% endblock %}
{% block toolbar %}
{% if collector.firewall %}
{% set icon %}
{{ source('@Security/Collector/icon.svg') }}
<span class="sf-toolbar-value">{{ collector.user|default('n/a') }}</span>
{% endset %}
{% set text %}
{% if collector.impersonated %}
<div class="sf-toolbar-info-group">
<div class="sf-toolbar-info-piece">
<b>Impersonator</b>
<span>{{ collector.impersonatorUser }}</span>
</div>
</div>
{% endif %}
<div class="sf-toolbar-info-group">
{% if collector.enabled %}
{% if collector.token %}
<div class="sf-toolbar-info-piece">
<b>Logged in as</b>
<span>{{ collector.user }}</span>
</div>
<div class="sf-toolbar-info-piece">
<b>Authenticated</b>
<span class="sf-toolbar-status sf-toolbar-status-{{ collector.authenticated ? 'green' : 'yellow' }}">{{ collector.authenticated ? 'Yes' : 'No' }}</span>
</div>
<div class="sf-toolbar-info-piece">
<b>Roles</b>
<span>
{% set remainingRoles = collector.roles|slice(1) %}
{{ collector.roles|first }}
{% if remainingRoles is not empty %}
+
<abbr title="{{ remainingRoles|join(', ') }}">
{{ remainingRoles|length }} more
</abbr>
{% endif %}
</span>
</div>
{% if collector.supportsRoleHierarchy %}
<div class="sf-toolbar-info-piece">
<b>Inherited Roles</b>
<span>
{% if collector.inheritedRoles is empty %}
none
{% else %}
{% set remainingRoles = collector.inheritedRoles|slice(1) %}
{{ collector.inheritedRoles|first }}
{% if remainingRoles is not empty %}
+
<abbr title="{{ remainingRoles|join(', ') }}">
{{ remainingRoles|length }} more
</abbr>
{% endif %}
{% endif %}
</span>
</div>
{% endif %}
<div class="sf-toolbar-info-piece">
<b>Token class</b>
<span>{{ collector.tokenClass|abbr_class }}</span>
</div>
{% else %}
<div class="sf-toolbar-info-piece">
<b>Authenticated</b>
<span class="sf-toolbar-status sf-toolbar-status-yellow">No</span>
</div>
{% endif %}
{% if collector.firewall %}
<div class="sf-toolbar-info-piece">
<b>Firewall name</b>
<span>{{ collector.firewall.name }}</span>
</div>
{% endif %}
{% if collector.token and collector.logoutUrl %}
<div class="sf-toolbar-info-piece">
<b>Actions</b>
<span>
<a href="{{ collector.logoutUrl }}">Logout</a>
{% if collector.impersonated and collector.impersonationExitPath %}
| <a href="{{ collector.impersonationExitPath }}">Exit impersonation</a>
{% endif %}
</span>
</div>
{% endif %}
{% else %}
<div class="sf-toolbar-info-piece">
<span>The security is disabled.</span>
</div>
{% endif %}
</div>
{% endset %}
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url }) }}
{% endif %}
{% endblock %}
{% block menu %}
<span class="label {{ not collector.firewall or not collector.token ? 'disabled' }}">
<span class="icon">{{ source('@Security/Collector/icon.svg') }}</span>
<strong>Security</strong>
</span>
{% endblock %}
{% block panel %}
<h2>Security</h2>
{% if collector.enabled %}
<div class="sf-tabs">
<div class="tab {{ collector.token is empty ? 'disabled' }}">
<h3 class="tab-title">Token</h3>
<div class="tab-content">
{% if collector.token %}
<div class="metrics">
<div class="metric">
<span class="value">{{ collector.user }}</span>
<span class="label">Username</span>
</div>
<div class="metric">
<span class="value">{{ source('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }}</span>
<span class="label">Authenticated</span>
</div>
</div>
<table>
<thead>
<tr>
<th scope="col" class="key">Property</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th>Roles</th>
<td>
{{ collector.roles is empty ? 'none' : profiler_dump(collector.roles, maxDepth=1) }}
{% if not collector.authenticated and collector.roles is empty %}
<p class="help">User is not authenticated probably because they have no roles.</p>
{% endif %}
</td>
</tr>
{% if collector.supportsRoleHierarchy %}
<tr>
<th>Inherited Roles</th>
<td>{{ collector.inheritedRoles is empty ? 'none' : profiler_dump(collector.inheritedRoles, maxDepth=1) }}</td>
</tr>
{% endif %}
{% if collector.token %}
<tr>
<th>Token</th>
<td>{{ profiler_dump(collector.token) }}</td>
</tr>
{% endif %}
</tbody>
</table>
{% elseif collector.enabled %}
<div class="empty">
<p>There is no security token.</p>
</div>
{% endif %}
</div>
</div>
<div class="tab {{ (not collector.firewall or collector.firewall.security_enabled is empty) ? 'disabled' }}">
<h3 class="tab-title">Firewall</h3>
<div class="tab-content">
{% if collector.firewall %}
<div class="metrics">
<div class="metric">
<span class="value">{{ collector.firewall.name }}</span>
<span class="label">Name</span>
</div>
<div class="metric">
<span class="value">{{ source('@WebProfiler/Icon/' ~ (collector.firewall.security_enabled ? 'yes' : 'no') ~ '.svg') }}</span>
<span class="label">Security enabled</span>
</div>
<div class="metric">
<span class="value">{{ source('@WebProfiler/Icon/' ~ (collector.firewall.stateless ? 'yes' : 'no') ~ '.svg') }}</span>
<span class="label">Stateless</span>
</div>
</div>
{% if collector.firewall.security_enabled %}
<h4>Configuration</h4>
<table>
<thead>
<tr>
<th scope="col" class="key">Key</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th>provider</th>
<td>{{ collector.firewall.provider ?: '(none)' }}</td>
</tr>
<tr>
<th>context</th>
<td>{{ collector.firewall.context ?: '(none)' }}</td>
</tr>
<tr>
<th>entry_point</th>
<td>{{ collector.firewall.entry_point ?: '(none)' }}</td>
</tr>
<tr>
<th>user_checker</th>
<td>{{ collector.firewall.user_checker ?: '(none)' }}</td>
</tr>
<tr>
<th>access_denied_handler</th>
<td>{{ collector.firewall.access_denied_handler ?: '(none)' }}</td>
</tr>
<tr>
<th>access_denied_url</th>
<td>{{ collector.firewall.access_denied_url ?: '(none)' }}</td>
</tr>
<tr>
<th>authenticators</th>
<td>{{ collector.firewall.authenticators is empty ? '(none)' : profiler_dump(collector.firewall.authenticators, maxDepth=1) }}</td>
</tr>
</tbody>
</table>
{% endif %}
{% endif %}
</div>
</div>
<div class="tab {{ collector.listeners|default([]) is empty ? 'disabled' }}">
<h3 class="tab-title">Listeners</h3>
<div class="tab-content">
{% if collector.listeners|default([]) is empty %}
<div class="empty">
<p>No security listeners have been recorded. Check that debugging is enabled in the kernel.</p>
</div>
{% else %}
<table>
<thead>
<tr>
<th>Listener</th>
<th>Duration</th>
<th>Response</th>
</tr>
</thead>
{% set previous_event = (collector.listeners|first) %}
{% for listener in collector.listeners %}
{% if loop.first or listener != previous_event %}
{% if not loop.first %}
</tbody>
{% endif %}
<tbody>
{% set previous_event = listener %}
{% endif %}
<tr>
<td class="font-normal">{{ profiler_dump(listener.stub) }}</td>
<td class="no-wrap">{{ '%0.2f'|format(listener.time * 1000) }} ms</td>
<td class="font-normal">{{ listener.response ? profiler_dump(listener.response) : '(none)' }}</td>
</tr>
{% if loop.last %}
</tbody>
{% endif %}
{% endfor %}
</table>
{% endif %}
</div>
</div>
<div class="tab {{ collector.authenticators|default([]) is empty ? 'disabled' }}">
<h3 class="tab-title">Authenticators</h3>
<div class="tab-content">
{% if collector.authenticators|default([]) is not empty %}
<table class="authenticators">
<thead>
<tr>
<th>Authenticator</th>
<th>Supports</th>
<th>Authenticated</th>
<th>Duration</th>
<th>Passport</th>
<th>Badges</th>
</tr>
</thead>
{% set previous_event = (collector.listeners|first) %}
{% for authenticator in collector.authenticators %}
{% if loop.first or authenticator != previous_event %}
{% if not loop.first %}
</tbody>
{% endif %}
<tbody>
{% set previous_event = authenticator %}
{% endif %}
<tr>
<td class="font-normal">{{ profiler_dump(authenticator.stub) }}</td>
<td class="no-wrap">{{ source('@WebProfiler/Icon/' ~ (authenticator.supports ? 'yes' : 'no') ~ '.svg') }}</td>
<td class="no-wrap">{{ authenticator.authenticated is not null ? source('@WebProfiler/Icon/' ~ (authenticator.authenticated ? 'yes' : 'no') ~ '.svg') : '' }}</td>
<td class="no-wrap">{{ '%0.2f'|format(authenticator.duration * 1000) }} ms</td>
<td class="font-normal">{{ authenticator.passport ? profiler_dump(authenticator.passport) : '(none)' }}</td>
<td class="font-normal">
{% for badge in authenticator.badges ?? [] %}
<span class="badge badge-{{ badge.resolved ? 'resolved' : 'not_resolved' }}">
{{ badge.stub|abbr_class }}
</span>
{% else %}
(none)
{% endfor %}
</td>
</tr>
{% if loop.last %}
</tbody>
{% endif %}
{% endfor %}
</table>
{% else %}
<div class="empty">
<p>No authenticators have been recorded. Check previous profiles on your authentication endpoint.</p>
</div>
{% endif %}
</div>
</div>
<div class="tab {{ collector.accessDecisionLog|default([]) is empty ? 'disabled' }}">
<h3 class="tab-title">Access Decision</h3>
<div class="tab-content">
{% if collector.voters|default([]) is not empty %}
<div class="metrics">
<div class="metric">
<span class="value">{{ collector.voterStrategy|default('unknown') }}</span>
<span class="label">Strategy</span>
</div>
</div>
<table class="voters">
<thead>
<tr>
<th>#</th>
<th>Voter class</th>
</tr>
</thead>
<tbody>
{% for voter in collector.voters %}
<tr>
<td class="font-normal text-small text-muted nowrap">{{ loop.index }}</td>
<td class="font-normal">{{ profiler_dump(voter) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if collector.accessDecisionLog|default([]) is not empty %}
<h2>Access decision log</h2>
<table class="decision-log">
<col style="width: 30px">
<col style="width: 120px">
<col style="width: 25%">
<col style="width: 60%">
<thead>
<tr>
<th>#</th>
<th>Result</th>
<th>Attributes</th>
<th>Object</th>
</tr>
</thead>
<tbody>
{% for decision in collector.accessDecisionLog %}
<tr class="voter_result">
<td class="font-normal text-small text-muted nowrap">{{ loop.index }}</td>
<td class="font-normal">
{{ decision.result
? '<span class="label status-success same-width">GRANTED</span>'
: '<span class="label status-error same-width">DENIED</span>'
}}
</td>
<td>
{% if decision.attributes|length == 1 %}
{% set attribute = decision.attributes|first %}
{% if attribute.expression is defined %}
Expression: <pre><code>{{ attribute.expression }}</code></pre>
{% elseif attribute.type == 'string' %}
{{ attribute }}
{% else %}
{{ profiler_dump(attribute) }}
{% endif %}
{% else %}
{{ profiler_dump(decision.attributes) }}
{% endif %}
</td>
<td>{{ profiler_dump(decision.seek('object')) }}</td>
</tr>
<tr class="voter_details">
<td></td>
<td colspan="3">
{% if decision.voter_details is not empty %}
{% set voter_details_id = 'voter-details-' ~ loop.index %}
<div id="{{ voter_details_id }}" class="sf-toggle-content sf-toggle-hidden">
<table>
<tbody>
{% for voter_detail in decision.voter_details %}
<tr>
<td class="font-normal">{{ profiler_dump(voter_detail['class']) }}</td>
{% if collector.voterStrategy == 'unanimous' %}
<td class="font-normal text-small">attribute {{ voter_detail['attributes'][0] }}</td>
{% endif %}
<td class="font-normal text-small">
{% if voter_detail['vote'] == constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface::ACCESS_GRANTED') %}
ACCESS GRANTED
{% elseif voter_detail['vote'] == constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface::ACCESS_ABSTAIN') %}
ACCESS ABSTAIN
{% elseif voter_detail['vote'] == constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface::ACCESS_DENIED') %}
ACCESS DENIED
{% else %}
unknown ({{ voter_detail['vote'] }})
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<a class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ voter_details_id }}" data-toggle-alt-content="Hide voter details">Show voter details</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}