You can change your name, your email address and enable ``Two factor authentication``.
+If the wallabag instance has more than one enabled user, you can delete your account here. **Take care, we delete all your data**.
+
Two factor authentication
~~~~~~~~~~~~~~~~~~~~~~~~~
Vous pouvez ici modifier votre nom, votre adresse email et activer la ``Double authentification``.
+Si l'instance de wallabag compte plus d'un utilisateur actif, vous pouvez supprimer ici votre compte. **Attention, nous supprimons toutes vos données**.
+
Double authentification (2FA)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// testing if database driver exists
$fulfilled = true;
- $label = '<comment>PDO Driver</comment>';
+ $label = '<comment>PDO Driver (%s)</comment>';
$status = '<info>OK!</info>';
$help = '';
$help = 'Database driver "'.$this->getContainer()->getParameter('database_driver').'" is not installed.';
}
- $rows[] = [$label, $status, $help];
+ $rows[] = [sprintf($label, $this->getContainer()->getParameter('database_driver')), $status, $help];
// testing if connection to the database can be etablished
$label = '<comment>Database connection</comment>';
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Wallabag\CoreBundle\Entity\Config;
use Wallabag\CoreBundle\Entity\TaggingRule;
use Wallabag\CoreBundle\Form\Type\ConfigType;
'token' => $config->getRssToken(),
],
'twofactor_auth' => $this->getParameter('twofactor_auth'),
+ 'enabled_users' => $this->getDoctrine()
+ ->getRepository('WallabagUserBundle:User')
+ ->getSumEnabledUsers(),
]);
}
return $config;
}
+
+ /**
+ * Delete account for current user.
+ *
+ * @Route("/account/delete", name="delete_account")
+ *
+ * @param Request $request
+ *
+ * @throws AccessDeniedHttpException
+ *
+ * @return \Symfony\Component\HttpFoundation\RedirectResponse
+ */
+ public function deleteAccountAction(Request $request)
+ {
+ $enabledUsers = $this->getDoctrine()
+ ->getRepository('WallabagUserBundle:User')
+ ->getSumEnabledUsers();
+
+ if ($enabledUsers <= 1) {
+ throw new AccessDeniedHttpException();
+ }
+
+ $user = $this->getUser();
+
+ // logout current user
+ $this->get('security.token_storage')->setToken(null);
+ $request->getSession()->invalidate();
+
+ $em = $this->get('fos_user.user_manager');
+ $em->deleteUser($user);
+
+ return $this->redirect($this->generateUrl('fos_user_security_login'));
+ }
}
name_label: 'Navn'
email_label: 'Emailadresse'
# twoFactorAuthentication_label: 'Two factor authentication'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'Gammel adgangskode'
new_password_label: 'Ny adgangskode'
name_label: 'Name'
email_label: 'E-Mail-Adresse'
twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'Altes Kennwort'
new_password_label: 'Neues Kennwort'
name_label: 'Name'
email_label: 'Email'
twoFactorAuthentication_label: 'Two factor authentication'
+ delete:
+ title: Delete my account (danger zone !)
+ description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ confirm: Are you really sure? (it can't be UNDONE)
+ button: Delete my account
form_password:
old_password_label: 'Current password'
new_password_label: 'New password'
name_label: 'Nombre'
email_label: 'Direccion e-mail'
twoFactorAuthentication_label: 'Autentificación de dos factores'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'Contraseña actual'
new_password_label: 'Nueva contraseña'
name_label: 'نام'
email_label: 'نشانی ایمیل'
twoFactorAuthentication_label: 'تأیید ۲مرحلهای'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'رمز قدیمی'
new_password_label: 'رمز تازه'
name_label: 'Nom'
email_label: 'Adresse e-mail'
twoFactorAuthentication_label: 'Double authentification'
+ delete:
+ title: Supprimer mon compte (attention danger !)
+ description: Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c'est IRRÉVERSIBLE). Vous serez ensuite déconnecté.
+ confirm: Vous êtes vraiment sûr ? (c'est IRRÉVERSIBLE !)
+ button: 'Supprimer mon compte'
form_password:
old_password_label: 'Mot de passe actuel'
new_password_label: 'Nouveau mot de passe'
name_label: 'Nome'
email_label: 'E-mail'
twoFactorAuthentication_label: 'Two factor authentication'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'Password corrente'
new_password_label: 'Nuova password'
internal_settings: 'Configuracion interna'
import: 'Importar'
howto: 'Ajuda'
- developer: 'Desvolopador'
+ developer: 'Desvolopaire'
logout: 'Desconnexion'
about: 'A prepaus'
search: 'Cercar'
save_link: 'Enregistrar un novèl article'
back_to_unread: 'Tornar als articles pas legits'
- # users_management: 'Users management'
+ users_management: 'Gestion dels utilizaires'
top:
add_new_entry: 'Enregistrar un novèl article'
search: 'Cercar'
social: 'Social'
powered_by: 'propulsat per'
about: 'A prepaus'
- # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
+ stats: "Dempuèi %user_creation% avètz legit %nb_archives% articles. Es a l'entorn de %per_day% per jorn !"
config:
page_title: 'Configuracion'
name_label: 'Nom'
email_label: 'Adreça de corrièl'
twoFactorAuthentication_label: 'Dobla autentificacion'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'Senhal actual'
new_password_label: 'Senhal novèl'
if_label: 'se'
then_tag_as_label: 'alara atribuir las etiquetas'
delete_rule_label: 'suprimir'
- # edit_rule_label: 'edit'
+ edit_rule_label: 'modificar'
rule_label: 'Règla'
tags_label: 'Etiquetas'
faq:
is_public_label: 'Public'
save_label: 'Enregistrar'
public:
- # shared_by_wallabag: "This article has been shared by <a href='%wallabag_instance%'>wallabag</a>"
+ shared_by_wallabag: "Aqueste article es estat partejat per <a href='%wallabag_instance%'>wallabag</a>"
about:
page_title: 'A prepaus'
quickstart:
page_title: 'Per ben començar'
- # more: 'More…'
+ more: 'Mai…'
intro:
title: 'Benvenguda sus wallabag !'
paragraph_1: "Anem vos guidar per far lo torn de la proprietat e vos presentar unas fonccionalitats que vos poirián interessar per vos apropriar aquesta aisina."
paragraph_2: 'Seguètz-nos '
configure:
- title: "Configuratz l'aplicacio"
- # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
+ title: "Configuratz l'aplicacion"
+ description: "Per fin d'aver una aplicacion que vos va ben, anatz veire la configuracion de wallabag."
language: "Cambiatz la lenga e l'estil de l'aplicacion"
rss: 'Activatz los fluxes RSS'
tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles'
import: 'Configurar los impòrt'
first_steps:
title: 'Primièrs passes'
- # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
+ description: "Ara wallabag es ben configurat, es lo moment d'archivar lo web. Podètz clicar sul signe + a man drecha amont per ajustar un ligam."
new_article: 'Ajustatz vòstre primièr article'
unread_articles: 'E racaptatz-lo !'
migrate:
readability: 'Migrar dempuèi Readability'
instapaper: 'Migrar dempuèi Instapaper'
developer:
- title: 'Pels desvolopadors'
- # description: 'We also thought to the developers: Docker, API, translations, etc.'
+ title: 'Pels desvolopaires'
+ description: 'Avèm tanben pensat als desvolopaires : Docker, API, traduccions, etc.'
create_application: 'Crear vòstra aplicacion tèrça'
- # use_docker: 'Use Docker to install wallabag'
+ use_docker: 'Utilizar Docker per installar wallabag'
docs:
title: 'Documentacion complèta'
- # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
- annotate: 'Anotatar vòstre article'
+ description: "I a un fum de fonccionalitats dins wallabag. Esitetz pas a legir lo manual per las conéisser e aprendre a las utilizar."
+ annotate: 'Anotar vòstre article'
export: 'Convertissètz vòstres articles en ePub o en PDF'
search_filters: "Aprenètz a utilizar lo motor de recèrca e los filtres per retrobar l'article que vos interèssa"
fetching_errors: "Qué far se mon article es pas recuperat coma cal ?"
warn_message_2: "Se suprimissètz un client, totas las aplicacions que l'emplegan foncionaràn pas mai amb vòstre compte wallabag."
action: 'Suprimir aqueste client'
client:
- page_title: 'Desvlopador > Novèl client'
+ page_title: 'Desvolopaire > Novèl client'
page_description: "Anatz crear un novèl client. Mercés de cumplir l'url de redireccion cap a vòstra aplicacion."
form:
name_label: "Nom del client"
save_label: 'Crear un novèl client'
action_back: 'Retorn'
client_parameter:
- page_title: 'Desvolopador > Los paramètres de vòstre client'
+ page_title: 'Desvolopaire > Los paramètres de vòstre client'
page_description: 'Vaquí los paramètres de vòstre client'
field_name: 'Nom del client'
field_id: 'ID Client'
back: 'Retour'
read_howto: 'Legir "cossí crear ma primièra aplicacion"'
howto:
- page_title: 'Desvolopador > Cossí crear ma primièra aplicacion'
+ page_title: 'Desvolopaire > Cossí crear ma primièra aplicacion'
description:
paragraph_1: "Las comandas seguentas utilizan la <a href=\"https://github.com/jkbrzt/httpie\">bibliotèca HTTPie</a>. Asseguratz-vos que siasqueòu installadas abans de l'utilizar."
paragraph_2: "Vos cal un geton per escambiar entre vòstra aplicacion e l'API de wallabar."
back: 'Retorn'
user:
- # page_title: Users management
- # new_user: Create a new user
- # edit_user: Edit an existing user
- # description: "Here you can manage all users (create, edit and delete)"
- # list:
- # actions: Actions
- # edit_action: Edit
- # yes: Yes
- # no: No
- # create_new_one: Create a new user
+ page_title: 'Gestion dels utilizaires'
+ new_user: 'Crear un novèl utilizaire'
+ edit_user: 'Modificar un utilizaire existent'
+ description: "Aquí podètz gerir totes los utilizaires (crear, modificar e suprimir)"
+ list:
+ actions: 'Accions'
+ edit_action: 'Modificar'
+ yes: 'Òc'
+ no: 'Non'
+ create_new_one: 'Crear un novèl utilizaire'
form:
username_label: "Nom d'utilizaire"
- # name_label: 'Name'
+ name_label: 'Nom'
password_label: 'Senhal'
repeat_new_password_label: 'Confirmatz vòstre novèl senhal'
plain_password_label: 'Senhal en clar'
email_label: 'Adreça de corrièl'
- # enabled_label: 'Enabled'
- # locked_label: 'Locked'
- # last_login_label: 'Last login'
- # twofactor_label: Two factor authentication
- # save: Save
- # delete: Delete
- # delete_confirm: Are you sure?
- # back_to_list: Back to list
+ enabled_label: 'Actiu'
+ locked_label: 'Varrolhat'
+ last_login_label: 'Darrièra connexion'
+ twofactor_label: 'Autentificacion doble-factor'
+ save: 'Enregistrar'
+ delete: 'Suprimir'
+ delete_confirm: 'Sètz segur ?'
+ back_to_list: 'Tornar a la lista'
flashes:
config:
rss_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn'
tagging_rules_updated: 'Règlas misa a jorn'
tagging_rules_deleted: 'Règla suprimida'
- user_added: 'Utilizaire "%username%" apondut'
+ user_added: 'Utilizaire "%username%" ajustat'
rss_token_updated: 'Geton RSS mes a jorn'
entry:
notice:
entry_reloaded_failed: "L'article es estat cargat de nòu mai la recuperacion del contengut a fracassat"
entry_archived: 'Article marcat coma legit'
entry_unarchived: 'Article marcat coma pas legit'
- entry_starred: 'Article apondut dins los favorits'
+ entry_starred: 'Article ajustat dins los favorits'
entry_unstarred: 'Article quitat dels favorits'
entry_deleted: 'Article suprimit'
tag:
notice:
- tag_added: 'Etiqueta aponduda'
+ tag_added: 'Etiqueta ajustada'
import:
notice:
failed: "L'importacion a fracassat, mercés de tornar ensajar"
name_label: 'Nazwa'
email_label: 'Adres email'
twoFactorAuthentication_label: 'Autoryzacja dwuetapowa'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'Stare hasło'
new_password_label: 'Nowe hasło'
name_label: 'Nume'
email_label: 'E-mail'
# twoFactorAuthentication_label: 'Two factor authentication'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'Parola veche'
new_password_label: 'Parola nouă'
name_label: 'İsim'
email_label: 'E-posta'
twoFactorAuthentication_label: 'İki adımlı doğrulama'
+ delete:
+ # title: Delete my account (danger zone !)
+ # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
+ # confirm: Are you really sure? (it can't be UNDONE)
+ # button: Delete my account
form_password:
old_password_label: 'Eski şifre'
new_password_label: 'Yeni şifre'
{{ form_widget(form.user.save) }}
</form>
+ {% if enabled_users > 1 %}
+ <h2>{{ 'config.form_user.delete.title'|trans }}</h2>
+
+ <p>{{ 'config.form_user.delete.description'|trans }}</p>
+ <a href="{{ path('delete_account') }}" onclick="return confirm('{{ 'config.form_user.delete.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red delete-account">
+ {{ 'config.form_user.delete.button'|trans }}
+ </a>
+ {% endif %}
+
<h2>{{ 'config.tab_menu.password'|trans }}</h2>
{{ form_start(form.pwd) }}
{{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
{{ form_widget(form.user._token) }}
</form>
+
+ {% if enabled_users > 1 %}
+ <br /><hr /><br />
+
+ <div class="row">
+ <h5>{{ 'config.form_user.delete.title'|trans }}</h5>
+ <p>{{ 'config.form_user.delete.description'|trans }}</p>
+ <a href="{{ path('delete_account') }}" onclick="return confirm('{{ 'config.form_user.delete.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red delete-account">
+ {{ 'config.form_user.delete.button'|trans }}
+ </a>
+ </div>
+ {% endif %}
</div>
<div id="set4" class="col s12">
->getQuery()
->getSingleResult();
}
+
+ /**
+ * Count how many users are enabled.
+ *
+ * @return int
+ */
+ public function getSumEnabledUsers()
+ {
+ return $this->createQueryBuilder('u')
+ ->select('count(u)')
+ ->andWhere('u.expired = false')
+ ->getQuery()
+ ->getSingleScalarResult();
+ }
}
namespace Tests\Wallabag\CoreBundle\Controller;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
+use Wallabag\CoreBundle\Entity\Config;
+use Wallabag\UserBundle\Entity\User;
class ConfigControllerTest extends WallabagCoreTestCase
{
$config->set('demo_mode_enabled', 0);
$config->set('demo_mode_username', 'wallabag');
}
+
+ public function testDeleteUserButtonVisibility()
+ {
+ $this->logInAs('admin');
+ $client = $this->getClient();
+
+ $crawler = $client->request('GET', '/config');
+
+ $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+ $this->assertContains('config.form_user.delete.button', $body[0]);
+
+ $em = $client->getContainer()->get('doctrine.orm.entity_manager');
+
+ $user = $em
+ ->getRepository('WallabagUserBundle:User')
+ ->findOneByUsername('empty');
+ $user->setExpired(1);
+ $em->persist($user);
+
+ $user = $em
+ ->getRepository('WallabagUserBundle:User')
+ ->findOneByUsername('bob');
+ $user->setExpired(1);
+ $em->persist($user);
+
+ $em->flush();
+
+ $crawler = $client->request('GET', '/config');
+
+ $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+ $this->assertNotContains('config.form_user.delete.button', $body[0]);
+
+ $client->request('GET', '/account/delete');
+ $this->assertEquals(403, $client->getResponse()->getStatusCode());
+
+ $user = $em
+ ->getRepository('WallabagUserBundle:User')
+ ->findOneByUsername('empty');
+ $user->setExpired(0);
+ $em->persist($user);
+
+ $user = $em
+ ->getRepository('WallabagUserBundle:User')
+ ->findOneByUsername('bob');
+ $user->setExpired(0);
+ $em->persist($user);
+
+ $em->flush();
+ }
+
+ public function testDeleteAccount()
+ {
+ $client = $this->getClient();
+ $em = $client->getContainer()->get('doctrine.orm.entity_manager');
+
+ $user = new User();
+ $user->setName('Wallace');
+ $user->setEmail('wallace@wallabag.org');
+ $user->setUsername('wallace');
+ $user->setPlainPassword('wallace');
+ $user->setEnabled(true);
+ $user->addRole('ROLE_SUPER_ADMIN');
+
+ $em->persist($user);
+
+ $config = new Config($user);
+
+ $config->setTheme('material');
+ $config->setItemsPerPage(30);
+ $config->setReadingSpeed(1);
+ $config->setLanguage('en');
+ $config->setPocketConsumerKey('xxxxx');
+
+ $em->persist($config);
+ $em->flush();
+
+ $this->logInAs('wallace');
+ $loggedInUserId = $this->getLoggedInUserId();
+
+ // create entry to check after user deletion
+ // that this entry is also deleted
+ $crawler = $client->request('GET', '/new');
+
+ $this->assertEquals(200, $client->getResponse()->getStatusCode());
+
+ $form = $crawler->filter('form[name=entry]')->form();
+ $data = [
+ 'entry[url]' => $url = 'https://github.com/wallabag/wallabag',
+ ];
+
+ $client->submit($form, $data);
+ $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+ $crawler = $client->request('GET', '/config');
+
+ $deleteLink = $crawler->filter('.delete-account')->last()->link();
+
+ $client->click($deleteLink);
+ $this->assertEquals(302, $client->getResponse()->getStatusCode());
+
+ $em = $client->getContainer()->get('doctrine.orm.entity_manager');
+ $user = $em
+ ->getRepository('WallabagUserBundle:User')
+ ->createQueryBuilder('u')
+ ->where('u.username = :username')->setParameter('username', 'wallace')
+ ->getQuery()
+ ->getOneOrNullResult()
+ ;
+
+ $this->assertNull($user);
+
+ $entries = $client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->findByUser($loggedInUserId);
+
+ $this->assertEmpty($entries);
+ }
}