mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-23 10:18:56 +02:00
Added the possibility to delete a U2F key.
This commit is contained in:
parent
069293a843
commit
3e56352688
7 changed files with 89 additions and 24 deletions
|
@ -297,11 +297,17 @@ class AjaxUI {
|
||||||
/**
|
/**
|
||||||
* Submits the given form via ajax.
|
* Submits the given form via ajax.
|
||||||
* @param form The form that will be submmitted.
|
* @param form The form that will be submmitted.
|
||||||
|
* @param btn The btn via which the form is submitted
|
||||||
*/
|
*/
|
||||||
public submitForm(form)
|
public submitForm(form, btn = null)
|
||||||
{
|
{
|
||||||
let options = ajaxUI.getFormOptions();
|
let options = ajaxUI.getFormOptions();
|
||||||
|
|
||||||
|
if(btn) {
|
||||||
|
options.data = {};
|
||||||
|
options.data[$(btn).attr('name')] = $(btn).attr('value');
|
||||||
|
}
|
||||||
|
|
||||||
$(form).ajaxSubmit(options);
|
$(form).ajaxSubmit(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,6 +190,9 @@ $(document).on("ajaxUI:start ajaxUI:reload", function() {
|
||||||
|
|
||||||
let form = this;
|
let form = this;
|
||||||
|
|
||||||
|
//Get the submit button
|
||||||
|
let btn = document.activeElement;
|
||||||
|
|
||||||
let title = $(this).data("title");
|
let title = $(this).data("title");
|
||||||
let message = $(this).data("message");
|
let message = $(this).data("message");
|
||||||
|
|
||||||
|
@ -199,7 +202,7 @@ $(document).on("ajaxUI:start ajaxUI:reload", function() {
|
||||||
callback: function(result) {
|
callback: function(result) {
|
||||||
//If the dialog was confirmed, then submit the form.
|
//If the dialog was confirmed, then submit the form.
|
||||||
if(result) {
|
if(result) {
|
||||||
ajaxUI.submitForm(form);
|
ajaxUI.submitForm(form, btn);
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,11 @@
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Parts\Part;
|
||||||
|
use App\Entity\UserSystem\U2FKey;
|
||||||
|
use App\Entity\UserSystem\User;
|
||||||
use App\Services\PasswordResetManager;
|
use App\Services\PasswordResetManager;
|
||||||
|
use App\Services\TFA\BackupCodeManager;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Gregwar\CaptchaBundle\Type\CaptchaType;
|
use Gregwar\CaptchaBundle\Type\CaptchaType;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
@ -29,6 +33,7 @@ use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
use Symfony\Component\Mailer\MailerInterface;
|
use Symfony\Component\Mailer\MailerInterface;
|
||||||
|
@ -164,6 +169,46 @@ class SecurityController extends AbstractController
|
||||||
'form' => $form->createView()
|
'form' => $form->createView()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @Route("/user/u2f_delete", name="u2f_delete", methods={"DELETE"})
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function removeU2FToken(Request $request, EntityManagerInterface $entityManager, BackupCodeManager $backupCodeManager)
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
if (!$user instanceof User) {
|
||||||
|
return new \RuntimeException('This controller only works only for Part-DB User objects!');
|
||||||
|
}
|
||||||
|
//When user change its settings, he should be logged in fully.
|
||||||
|
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
|
||||||
|
|
||||||
|
if ($this->isCsrfTokenValid('delete'.$user->getId(), $request->request->get('_token'))) {
|
||||||
|
if($request->request->has('key_id')) {
|
||||||
|
$key_id = $request->request->get('key_id');
|
||||||
|
$key_repo = $entityManager->getRepository(U2FKey::class);
|
||||||
|
/** @var U2FKey|null $u2f */
|
||||||
|
$u2f = $key_repo->find($key_id);
|
||||||
|
if($u2f === null) {
|
||||||
|
$this->addFlash('danger','tfa_u2f.u2f_delete.not_existing');
|
||||||
|
throw new \RuntimeException('Key not existing!');
|
||||||
|
}
|
||||||
|
|
||||||
|
//User can only delete its own U2F keys
|
||||||
|
if ($u2f->getUser() !== $user) {
|
||||||
|
$this->addFlash('danger', 'tfa_u2f.u2f_delete.access_denied');
|
||||||
|
throw new \RuntimeException('You can only delete your own U2F keys!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$backupCodeManager->disableBackupCodesIfUnused($user);
|
||||||
|
$entityManager->remove($u2f);
|
||||||
|
$entityManager->flush();
|
||||||
|
$this->addFlash('success', 'tfa.u2f.u2f_delete.success');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redirectToRoute('user_settings');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/logout", name="logout")
|
* @Route("/logout", name="logout")
|
||||||
|
|
|
@ -161,6 +161,15 @@ class U2FKey implements TwoFactorKeyInterface
|
||||||
return $this->user;
|
return $this->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primary key ID of this key
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getID() : int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the user this U2F key belongs to.
|
* Sets the user this U2F key belongs to.
|
||||||
* @param TwoFactorInterface $new_user
|
* @param TwoFactorInterface $new_user
|
||||||
|
|
|
@ -37,7 +37,7 @@ class BackupCodeManager
|
||||||
*/
|
*/
|
||||||
public function disableBackupCodesIfUnused(User $user)
|
public function disableBackupCodesIfUnused(User $user)
|
||||||
{
|
{
|
||||||
if($user->isU2FAuthEnabled() || $user->isGoogleAuthenticatorEnabled()) {
|
if($user->isGoogleAuthenticatorEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,12 +100,17 @@
|
||||||
|
|
||||||
{% if user.u2FKeys is not empty %}
|
{% if user.u2FKeys is not empty %}
|
||||||
<b>{% trans %}tfa_u2f.table_caption{% endtrans %}:</b>
|
<b>{% trans %}tfa_u2f.table_caption{% endtrans %}:</b>
|
||||||
|
<form action="{{ url('u2f_delete') }}" method="post" data-delete-form data-title="{% trans %}tfa_u2f.delete_u2f.confirm_title{% endtrans %}"
|
||||||
|
data-message="{% trans %}tfa_u2f.delete_u2f.confirm_message{% endtrans %}">
|
||||||
|
<input type="hidden" name="_method" value="DELETE">
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ user.id) }}">
|
||||||
<table class="table table-striped table-bordered table-sm mt-2">
|
<table class="table table-striped table-bordered table-sm mt-2">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th>
|
<th>#</th>
|
||||||
<th>{% trans %}tfa_u2f.keys.name{% endtrans %}</th>
|
<th>{% trans %}tfa_u2f.keys.name{% endtrans %}</th>
|
||||||
<th>{% trans %}tfa_u2f.keys.added_date{% endtrans %}</th>
|
<th>{% trans %}tfa_u2f.keys.added_date{% endtrans %}</th>
|
||||||
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -114,10 +119,12 @@
|
||||||
<td>{{ loop.index }}</td>
|
<td>{{ loop.index }}</td>
|
||||||
<td>{{ key.name }}</td>
|
<td>{{ key.name }}</td>
|
||||||
<td>{{ key.addedDate | format_datetime }}</td>
|
<td>{{ key.addedDate | format_datetime }}</td>
|
||||||
|
<td><button type="submit" class="btn btn-danger btn-sm" name="key_id" value="{{ key.id }}"><i class="fas fa-trash-alt fa-fw"></i> {% trans %}tfa_u2f.key_delete{% endtrans %}</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p><b>{% trans %}tfa_u2f.no_keys_registered{% endtrans %}</b></p>
|
<p><b>{% trans %}tfa_u2f.no_keys_registered{% endtrans %}</b></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -60,10 +60,5 @@ class BackupCodeManagerTest extends WebTestCase
|
||||||
$user->setGoogleAuthenticatorSecret('jskf');
|
$user->setGoogleAuthenticatorSecret('jskf');
|
||||||
$this->service->disableBackupCodesIfUnused($user);
|
$this->service->disableBackupCodesIfUnused($user);
|
||||||
$this->assertEquals($codes, $user->getBackupCodes());
|
$this->assertEquals($codes, $user->getBackupCodes());
|
||||||
|
|
||||||
$user->setGoogleAuthenticatorSecret('');
|
|
||||||
$user->addU2FKey(new U2FKey());
|
|
||||||
$this->service->disableBackupCodesIfUnused($user);
|
|
||||||
$this->assertEquals($codes, $user->getBackupCodes());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue