{% 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 .authenticator-name {
            align-items: center;
            display: flex;
            gap: 16px;
        }

        #collector-content .authenticators .toggle-button {
            margin-left: auto;
        }
        #collector-content .authenticators .sf-toggle-on .toggle-button {
            transform: rotate(180deg);
        }
        #collector-content .authenticators .toggle-button svg {
            display: block;
        }

        #collector-content .authenticators th,
        #collector-content .authenticators td {
            vertical-align: baseline;
        }
        #collector-content .authenticators th,
        #collector-content .authenticators td {
            vertical-align: baseline;
        }

        #collector-content .authenticators .label {
            display: block;
            text-align: center;
        }

        #collector-content .authenticator-data {
            box-shadow: none;
            margin: 0;
        }

        #collector-content .authenticator-data tr:first-child th,
        #collector-content .authenticator-data tr:first-child td {
            border-top: 0;
        }

        #collector-content .authenticators .badge {
            color: var(--white);
            display: inline-block;
            margin: 4px 0;
        }
        #collector-content .authenticators .badge.badge-resolved {
            background-color: var(--green-500);
        }
        #collector-content .authenticators .badge.badge-not_resolved {
            background-color: var(--yellow-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>

                            {% if collector.authProfileToken %}
                                <div class="metric">
                                    <span class="value">
                                        <a href="{{ path('_profiler', {token: collector.authProfileToken, panel: 'security'}) }}">
                                            {{- collector.authProfileToken -}}
                                        </a>
                                    </span>
                                    <span class="label">From</span>
                                </div>
                            {% endif %}
                        </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.
                                {% if collector.deauthProfileToken %}
                                    It was removed in
                                    <a href="{{ path('_profiler', {token: collector.deauthProfileToken, panel: 'security'}) }}">
                                        {{- collector.deauthProfileToken -}}
                                    </a>.
                                {% endif %}
                            </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">{{ listener.time is null ? '(none)' : '%0.2f ms'|format(listener.time * 1000) }}</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">
                            <colgroup>
                                <col>
                                <col style="width: 100%">
                            </colgroup>
                            <thead>
                            <tr>
                                <th scope="col">Status</th>
                                <th scope="col">Authenticator</th>
                            </tr>
                            </thead>
                            {% for i, authenticator in collector.authenticators %}
                                <tr class="sf-toggle"
                                    data-toggle-selector="#authenticator-{{ i }}"
                                    data-toggle-initial="{{ authenticator.authenticated is not null ? 'display' }}"
                                >
                                    <td class="font-normal text-small">
                                        {% if authenticator.authenticated %}
                                            {% set status_text, label_status = 'success', 'success' %}
                                        {% elseif authenticator.authenticated is null %}
                                            {% set status_text, label_status = 'skipped', false %}
                                        {% else %}
                                            {% set status_text, label_status = 'failure', 'error' %}
                                        {% endif %}
                                        <span class="label {{ label_status ? 'status-' ~ label_status }}">{{ status_text }}</span>
                                    </td>
                                    <td>
                                        <span class="authenticator-name">
                                            {{ profiler_dump(authenticator.stub) }}
                                            <button class="btn btn-link toggle-button" type="button">
                                                {{ source('@WebProfiler/Icon/chevron-down.svg') }}
                                            </button>
                                        </span>
                                        <div id="authenticator-{{ i }}" class="font-normal">
                                            {% if authenticator.supports is same as(false) %}
                                                <div class="empty">
                                                    <p>This authenticator did not support the request.</p>
                                                </div>
                                            {% elseif authenticator.authenticated is null %}
                                                <div class="empty">
                                                    <p>An authenticator ran before this one.</p>
                                                </div>
                                            {% else %}
                                                <table class="authenticator-data">
                                                    <colgroup>
                                                        <col>
                                                        <col style="width: 100%">
                                                    </colgroup>
                                                    <tr>
                                                        <th scope="row">Lazy</th>
                                                        <td>{{ authenticator.supports is null ? 'yes' : 'no' }}</td>
                                                    </tr>
                                                    <tr>
                                                        <th scope="row">Duration</th>
                                                        <td>{{ '%0.2f ms'|format(authenticator.duration * 1000) }}</td>
                                                    </tr>
                                                    {% if authenticator.passport %}
                                                        <tr>
                                                            <th scope="row">Passport</th>
                                                            <td>{{ profiler_dump(authenticator.passport) }}</td>
                                                        </tr>
                                                    {% endif %}
                                                    {% if authenticator.badges %}
                                                        <tr>
                                                            <th scope="row">Badges</th>
                                                            <td>
                                                                {% for badge in authenticator.badges %}
                                                                    <span class="badge badge-{{ badge.resolved ? 'resolved' : 'not_resolved' }}">
                                                                        {{ badge.stub|abbr_class }}
                                                                    </span>
                                                                {% endfor %}
                                                            </td>
                                                        </tr>
                                                    {% endif %}
                                                    {% if authenticator.exception %}
                                                        <tr>
                                                            <th scope="row">Exception</th>
                                                            <td>{{ profiler_dump(authenticator.exception) }}</td>
                                                        </tr>
                                                    {% endif %}
                                                </table>
                                            {% endif %}
                                        </div>
                                    </td>
                                </tr>
                            {% 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">
                                            {% set result = decision.result|default(null) %}
                                            {% if result is same as(true) %}
                                                <span class="label status-success same-width">GRANTED</span>
                                            {% elseif result is same as(false) %}
                                                <span class="label status-error same-width">DENIED</span>
                                            {% else %}
                                                <span class="label status-warning same-width">ERROR</span>
                                            {% endif %}
                                        </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') %}
                                                                    GRANTED
                                                                {% elseif voter_detail['vote'] == constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface::ACCESS_ABSTAIN') %}
                                                                    ABSTAIN
                                                                {% elseif voter_detail['vote'] == constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface::ACCESS_DENIED') %}
                                                                    DENIED
                                                                {% else %}
                                                                    unknown ({{ voter_detail['vote'] }})
                                                                {% endif %}
                                                                {% if voter_detail['reasons'] is not empty %}
                                                                    {% for voter_reason in voter_detail['reasons'] %}
                                                                        <br>{{ voter_reason }}
                                                                    {% endfor %}
                                                                {% 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 %}
