1
0
Fork 0
mirror of https://github.com/wallabag/wallabag.git synced 2025-06-27 16:36:00 +00:00

Protect tag_delete with a CSRF token

This commit is contained in:
Yassine Guedidi 2025-03-23 14:51:58 +01:00
parent cf49be6940
commit 27f0d94db7
4 changed files with 15 additions and 6 deletions

View file

@ -177,6 +177,7 @@ a.original:not(.waves-effect) {
.card-entry-tags a, .card-entry-tags a,
.card-entry-labels a, .card-entry-labels a,
.card-tag-labels a, .card-tag-labels a,
.card-tag-labels button,
.card-entry-labels-hidden a, .card-entry-labels-hidden a,
#list .chip a { #list .chip a {
text-decoration: none; text-decoration: none;

View file

@ -272,13 +272,17 @@ class TagController extends AbstractController
/** /**
* Delete a given tag for the current user. * Delete a given tag for the current user.
* *
* @Route("/tag/delete/{slug}", name="tag_delete") * @Route("/tag/delete/{slug}", name="tag_delete", methods={"POST"})
* @ParamConverter("tag", options={"mapping": {"slug": "slug"}}) * @ParamConverter("tag", options={"mapping": {"slug": "slug"}})
* *
* @return Response * @return Response
*/ */
public function removeTagAction(Tag $tag, Request $request, EntryRepository $entryRepository) public function removeTagAction(Tag $tag, Request $request, EntryRepository $entryRepository)
{ {
if (!$this->isCsrfTokenValid('tag-delete', $request->request->get('token'))) {
throw new BadRequestHttpException('Bad CSRF token.');
}
foreach ($tag->getEntriesByUserId($this->getUser()->getId()) as $entry) { foreach ($tag->getEntriesByUserId($this->getUser()->getId()) as $entry) {
$entryRepository->removeTag($this->getUser()->getId(), $tag); $entryRepository->removeTag($this->getUser()->getId(), $tag);
} }

View file

@ -28,9 +28,13 @@
<i class="material-icons">mode_edit</i> <i class="material-icons">mode_edit</i>
</a> </a>
{% endif %} {% endif %}
<a id="delete-{{ tag.slug }}" href="{{ path('tag_delete', {'slug': tag.slug, redirect: current_path}) }}" class="card-tag-icon card-tag-delete" onclick="return confirm('{{ 'tag.confirm.delete'|trans({'%name%': tag.label})|escape('js') }}')"> <form action="{{ path('tag_delete', {'slug': tag.slug, redirect: current_path}) }}" method="post" class="inline-block">
<input type="hidden" name="token" value="{{ csrf_token('tag-delete') }}"/>
<button type="submit" class="btn-link card-tag-icon card-tag-delete" onclick="return confirm('{{ 'tag.confirm.delete'|trans({'%name%': tag.label})|escape('js') }}')">
<i class="material-icons">delete</i> <i class="material-icons">delete</i>
</a> </button>
</form>
{% if app.user.config.feedToken %} {% if app.user.config.feedToken %}
<a rel="alternate" type="application/atom+xml" href="{{ path('tag_feed', {'username': app.user.username, 'token': app.user.config.feedToken, 'slug': tag.slug}) }}" class="card-tag-icon"><i class="material-icons">rss_feed</i></a> <a rel="alternate" type="application/atom+xml" href="{{ path('tag_feed', {'username': app.user.username, 'token': app.user.config.feedToken, 'slug': tag.slug}) }}" class="card-tag-icon"><i class="material-icons">rss_feed</i></a>
{% endif %} {% endif %}

View file

@ -168,8 +168,8 @@ class TagControllerTest extends WallabagCoreTestCase
$this->getEntityManager()->clear(); $this->getEntityManager()->clear();
$crawler = $client->request('GET', '/tag/list'); $crawler = $client->request('GET', '/tag/list');
$link = $crawler->filter('a[id="delete-' . $tag->getSlug() . '"]')->link(); $form = $crawler->filter('#tag-' . $tag->getId())->selectButton('delete')->form();
$client->click($link); $client->submit($form);
$tag = $client->getContainer() $tag = $client->getContainer()
->get(EntityManagerInterface::class) ->get(EntityManagerInterface::class)