diff options
| author | Dennis Fink | 2026-08-10 23:28:03 +0200 |
|---|---|---|
| committer | Dennis Fink | 2026-08-10 23:28:03 +0200 |
| commit | b3e12b975064f0873bdb4d2834cae75925387d6b (patch) | |
| tree | 92a7ce50f9a3e2b0a49aa32addd9c7e35062d91e /webmentions_ssg/templates/received.html | |
| parent | 5b39f70aa14cac635b6084170e9d0bd3f548b911 (diff) | |
| download | webmentions-ssg-b3e12b975064f0873bdb4d2834cae75925387d6b.tar.gz webmentions-ssg-b3e12b975064f0873bdb4d2834cae75925387d6b.zip | |
feat(core): add received webmention admin actions
Add authenticated delete and reverify actions to the received
webmentions admin view and protect them with CSRF validation.
Enable CSRF protection globally while exempting the public Webmention
endpoint.
Diffstat (limited to 'webmentions_ssg/templates/received.html')
| -rw-r--r-- | webmentions_ssg/templates/received.html | 97 |
1 files changed, 88 insertions, 9 deletions
diff --git a/webmentions_ssg/templates/received.html b/webmentions_ssg/templates/received.html index ea74557..64f225e 100644 --- a/webmentions_ssg/templates/received.html +++ b/webmentions_ssg/templates/received.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% from "bootstrap5/form.html" import render_form %} {% from "bootstrap5/pagination.html" import render_pagination %} {% block content %} <div class="d-flex justify-content-between align-items-center mb-3"> @@ -16,16 +17,20 @@ <th scope="col">Received</th> <th scope="col">Updated</th> <th scope="col">Reason</th> + <th scope="col">Actions</th> </tr> </thead> <tbody> {% for webmention in webmentions %} - {% if webmention.status == "verified" %} + {% if webmention.status == "received" %} + {% set row_class = "table-info" %} + {% set display_status = "Pending" %} + {% elif webmention.status == "verifying" %} + {% set row_class = "table-warning" %} + {% set display_status = "Verifying" %} + {% elif webmention.status == "verified" %} {% set row_class = "table-success" %} {% set display_status = "Verified" %} - {% elif webmention.status in ("received", "verifying") %} - {% set row_class = "table-warning" %} - {% set display_status = "Pending" %} {% else %} {% set row_class = "table-danger" %} {% set display_status = "Declined" %} @@ -51,19 +56,93 @@ </time> </td> <td>{{ webmention.failure_reason or "—" }}</td> + <td class="text-nowrap"> + <button type="button" + class="btn btn-sm btn-primary" + data-bs-toggle="modal" + data-bs-target="#confirmation-modal" + data-action="{{ url_for('root.reverify_received_webmention', identifier=webmention.uuid, page=webmentions.page) }}" + data-title="Reverify webmention?" + data-message="The webmention will be fetched and verified again." + data-confirm-label="Reverify" + data-confirm-class="btn-primary">Reverify</button> + <button type="button" + class="btn btn-sm btn-danger" + data-bs-toggle="modal" + data-bs-target="#confirmation-modal" + data-action="{{ url_for('root.delete_received_webmention', identifier=webmention.uuid, page=webmentions.page) }}" + data-title="Delete webmention?" + data-message="This permanently deletes the webmention and cannot be undone." + data-confirm-label="Delete" + data-confirm-class="btn-danger">Delete</button> + </td> </tr> {% endfor %} </tbody> </table> </div> {% if webmentions.pages > 1 %} - <div class="mt-3"> - {{ render_pagination(webmentions, - align="center", - size="sm") }} - </div> + <div class="mt-3">{{ render_pagination(webmentions) }}</div> {% endif %} + <div class="modal fade" + id="confirmation-modal" + tabindex="-1" + aria-labelledby="confirmation-modal-title" + aria-hidden="true"> + <div class="modal-dialog modal-dialog-centered"> + <div class="modal-content"> + <div class="modal-header"> + <h1 class="modal-title fs-5" id="confirmation-modal-title"></h1> + <button type="button" + class="btn-close" + data-bs-dismiss="modal" + aria-label="Close"></button> + </div> + <div class="modal-body"> + <p id="confirmation-modal-message" class="mb-0"></p> + </div> + <div class="modal-footer"> + {{ render_form(action_form, + id="confirmation-modal-form", + button_style="primary", + form_group_classes="mb-0") }} + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> + </div> + </div> + </div> + </div> {% else %} <p class="text-body-secondary">No Webmentions have been received yet.</p> {% endif %} {% endblock %} +{% block scripts %} + {{ super() }} + <script> + const confirmationModal = document.getElementById( + "confirmation-modal" + ); + + confirmationModal.addEventListener("show.bs.modal", (event) => { + const button = event.relatedTarget; + + const form = confirmationModal.querySelector( + "#confirmation-modal-form" + ); + const title = confirmationModal.querySelector( + "#confirmation-modal-title" + ); + const message = confirmationModal.querySelector( + "#confirmation-modal-message" + ); + const submit = form.querySelector("#submit"); + + form.action = button.dataset.action; + + title.textContent = button.dataset.title; + message.textContent = button.dataset.message; + + submit.value = button.dataset.confirmLabel; + submit.className = `btn ${button.dataset.confirmClass}`; + }); + </script> +{% endblock %} |
