mirror of
https://github.com/wallabag/wallabag.git
synced 2025-03-28 05:45:28 +00:00
Merge pull request #3798 from wallabag/update-two-factor-bundle
Enable OTP 2FA
This commit is contained in:
commit
2e5b3fa361
41 changed files with 1097 additions and 236 deletions
|
@ -13,5 +13,5 @@ insert_final_newline = true
|
|||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
[*akefile]
|
||||
indent_style = tab
|
||||
|
|
|
@ -51,13 +51,13 @@ install:
|
|||
|
||||
before_script:
|
||||
- PHP=$TRAVIS_PHP_VERSION
|
||||
- if [[ ! $PHP = hhvm* ]]; then echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi;
|
||||
# xdebug isn't enable for PHP 7.1
|
||||
- if [[ ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi
|
||||
- echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
|
||||
- phpenv config-rm xdebug.ini || echo "xdebug not available"
|
||||
- composer self-update --no-progress
|
||||
|
||||
script:
|
||||
- travis_wait bash composer install -o --no-interaction --no-progress --prefer-dist
|
||||
|
||||
- echo "travis_fold:start:prepare"
|
||||
- make prepare DB=$DB
|
||||
- echo "travis_fold:end:prepare"
|
||||
|
|
76
app/DoctrineMigrations/Version20181202073750.php
Normal file
76
app/DoctrineMigrations/Version20181202073750.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace Application\Migrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
|
||||
|
||||
/**
|
||||
* Add 2fa OTP stuff.
|
||||
*/
|
||||
final class Version20181202073750 extends WallabagMigration
|
||||
{
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
switch ($this->connection->getDatabasePlatform()->getName()) {
|
||||
case 'sqlite':
|
||||
$this->addSql('DROP INDEX UNIQ_1D63E7E5C05FB297');
|
||||
$this->addSql('DROP INDEX UNIQ_1D63E7E5A0D96FBF');
|
||||
$this->addSql('DROP INDEX UNIQ_1D63E7E592FC23A8');
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__' . $this->getTable('user', true) . ' AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication FROM ' . $this->getTable('user', true) . '');
|
||||
$this->addSql('DROP TABLE ' . $this->getTable('user', true) . '');
|
||||
$this->addSql('CREATE TABLE ' . $this->getTable('user', true) . ' (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(180) NOT NULL COLLATE BINARY, username_canonical VARCHAR(180) NOT NULL COLLATE BINARY, email VARCHAR(180) NOT NULL COLLATE BINARY, email_canonical VARCHAR(180) NOT NULL COLLATE BINARY, enabled BOOLEAN NOT NULL, password VARCHAR(255) NOT NULL COLLATE BINARY, last_login DATETIME DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, name CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, emailTwoFactor BOOLEAN NOT NULL, salt VARCHAR(255) DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, roles CLOB NOT NULL --(DC2Type:array)
|
||||
, googleAuthenticatorSecret VARCHAR(255) DEFAULT NULL, backupCodes CLOB DEFAULT NULL --(DC2Type:json_array)
|
||||
)');
|
||||
$this->addSql('INSERT INTO ' . $this->getTable('user', true) . ' (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, emailTwoFactor) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication FROM __temp__' . $this->getTable('user', true) . '');
|
||||
$this->addSql('DROP TABLE __temp__' . $this->getTable('user', true) . '');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON ' . $this->getTable('user', true) . ' (confirmation_token)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON ' . $this->getTable('user', true) . ' (email_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON ' . $this->getTable('user', true) . ' (username_canonical)');
|
||||
break;
|
||||
case 'mysql':
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD googleAuthenticatorSecret VARCHAR(191) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' CHANGE twoFactorAuthentication emailTwoFactor BOOLEAN NOT NULL');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' DROP trusted');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD backupCodes LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:json_array)\'');
|
||||
break;
|
||||
case 'postgresql':
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD googleAuthenticatorSecret VARCHAR(191) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' RENAME COLUMN twofactorauthentication TO emailTwoFactor');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' DROP trusted');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD backupCodes TEXT DEFAULT NULL');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
switch ($this->connection->getDatabasePlatform()->getName()) {
|
||||
case 'sqlite':
|
||||
$this->addSql('DROP INDEX UNIQ_1D63E7E592FC23A8');
|
||||
$this->addSql('DROP INDEX UNIQ_1D63E7E5A0D96FBF');
|
||||
$this->addSql('DROP INDEX UNIQ_1D63E7E5C05FB297');
|
||||
$this->addSql('CREATE TEMPORARY TABLE __temp__' . $this->getTable('user', true) . ' AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, emailTwoFactor FROM "' . $this->getTable('user', true) . '"');
|
||||
$this->addSql('DROP TABLE "' . $this->getTable('user', true) . '"');
|
||||
$this->addSql('CREATE TABLE "' . $this->getTable('user', true) . '" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, name CLOB DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL COLLATE BINARY, confirmation_token VARCHAR(255) DEFAULT NULL COLLATE BINARY, roles CLOB NOT NULL COLLATE BINARY, trusted CLOB DEFAULT NULL COLLATE BINARY)');
|
||||
$this->addSql('INSERT INTO "' . $this->getTable('user', true) . '" (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, emailTwoFactor FROM __temp__' . $this->getTable('user', true) . '');
|
||||
$this->addSql('DROP TABLE __temp__' . $this->getTable('user', true) . '');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON "' . $this->getTable('user', true) . '" (username_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON "' . $this->getTable('user', true) . '" (email_canonical)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON "' . $this->getTable('user', true) . '" (confirmation_token)');
|
||||
break;
|
||||
case 'mysql':
|
||||
$this->addSql('ALTER TABLE `' . $this->getTable('user') . '` DROP googleAuthenticatorSecret');
|
||||
$this->addSql('ALTER TABLE `' . $this->getTable('user') . '` CHANGE emailtwofactor twoFactorAuthentication BOOLEAN NOT NULL');
|
||||
$this->addSql('ALTER TABLE `' . $this->getTable('user') . '` ADD trusted TEXT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE `' . $this->getTable('user') . '` DROP backupCodes');
|
||||
break;
|
||||
case 'postgresql':
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' DROP googleAuthenticatorSecret');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' RENAME COLUMN emailTwoFactor TO twofactorauthentication');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD trusted TEXT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' DROP backupCodes');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -89,4 +89,22 @@ $(document).ready(() => {
|
|||
}
|
||||
};
|
||||
});
|
||||
|
||||
// mimic radio button because emailTwoFactor is a boolean
|
||||
$('#update_user_googleTwoFactor').on('change', () => {
|
||||
$('#update_user_emailTwoFactor').prop('checked', false);
|
||||
});
|
||||
|
||||
$('#update_user_emailTwoFactor').on('change', () => {
|
||||
$('#update_user_googleTwoFactor').prop('checked', false);
|
||||
});
|
||||
|
||||
// same mimic for super admin
|
||||
$('#user_googleTwoFactor').on('change', () => {
|
||||
$('#user_emailTwoFactor').prop('checked', false);
|
||||
});
|
||||
|
||||
$('#user_emailTwoFactor').on('change', () => {
|
||||
$('#user_googleTwoFactor').prop('checked', false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -50,25 +50,30 @@ $(document).ready(() => {
|
|||
$('#tag_label').focus();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#nav-btn-add').on('click', () => {
|
||||
toggleNav('.nav-panel-add', '#entry_url');
|
||||
return false;
|
||||
});
|
||||
|
||||
const materialAddForm = $('.nav-panel-add');
|
||||
materialAddForm.on('submit', () => {
|
||||
materialAddForm.addClass('disabled');
|
||||
$('input#entry_url', materialAddForm).prop('readonly', true).trigger('blur');
|
||||
});
|
||||
|
||||
$('#nav-btn-search').on('click', () => {
|
||||
toggleNav('.nav-panel-search', '#search_entry_term');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.close').on('click', (e) => {
|
||||
$(e.target).parent('.nav-panel-item').hide(100);
|
||||
$('.nav-panel-actions').show(100);
|
||||
$('.nav-panels').css('background', 'transparent');
|
||||
return false;
|
||||
});
|
||||
|
||||
$(window).scroll(() => {
|
||||
const s = $(window).scrollTop();
|
||||
const d = $(document).height();
|
||||
|
|
|
@ -198,10 +198,17 @@ fos_oauth_server:
|
|||
refresh_token_lifetime: 1209600
|
||||
|
||||
scheb_two_factor:
|
||||
trusted_computer:
|
||||
trusted_device:
|
||||
enabled: true
|
||||
cookie_name: wllbg_trusted_computer
|
||||
cookie_lifetime: 2592000
|
||||
lifetime: 2592000
|
||||
|
||||
backup_codes:
|
||||
enabled: "%twofactor_auth%"
|
||||
|
||||
google:
|
||||
enabled: "%twofactor_auth%"
|
||||
template: WallabagUserBundle:Authentication:form.html.twig
|
||||
|
||||
email:
|
||||
enabled: "%twofactor_auth%"
|
||||
|
|
|
@ -51,3 +51,11 @@ craue_config_settings_modify:
|
|||
|
||||
fos_js_routing:
|
||||
resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml"
|
||||
|
||||
2fa_login:
|
||||
path: /2fa
|
||||
defaults:
|
||||
_controller: "scheb_two_factor.form_controller:form"
|
||||
|
||||
2fa_login_check:
|
||||
path: /2fa_check
|
||||
|
|
|
@ -56,9 +56,17 @@ security:
|
|||
path: /logout
|
||||
target: /
|
||||
|
||||
two_factor:
|
||||
provider: fos_userbundle
|
||||
auth_form_path: 2fa_login
|
||||
check_path: 2fa_login_check
|
||||
|
||||
access_control:
|
||||
- { path: ^/api/(doc|version|info|user), roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
# force role for logout otherwise when 2fa enable, you won't be able to logout
|
||||
# https://github.com/scheb/two-factor-bundle/issues/168#issuecomment-430822478
|
||||
- { path: ^/logout, roles: [IS_AUTHENTICATED_ANONYMOUSLY, IS_AUTHENTICATED_2FA_IN_PROGRESS] }
|
||||
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: /(unread|starred|archive|all).xml$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
|
@ -67,5 +75,6 @@ security:
|
|||
- { path: ^/share, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/settings, roles: ROLE_SUPER_ADMIN }
|
||||
- { path: ^/annotations, roles: ROLE_USER }
|
||||
- { path: ^/2fa, role: IS_AUTHENTICATED_2FA_IN_PROGRESS }
|
||||
- { path: ^/users, roles: ROLE_SUPER_ADMIN }
|
||||
- { path: ^/, roles: ROLE_USER }
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"issues": "https://github.com/wallabag/wallabag/issues"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"php": ">=7.1.3",
|
||||
"ext-pcre": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-curl": "*",
|
||||
|
@ -70,7 +70,7 @@
|
|||
"friendsofsymfony/user-bundle": "2.0.*",
|
||||
"friendsofsymfony/oauth-server-bundle": "^1.5",
|
||||
"stof/doctrine-extensions-bundle": "^1.2",
|
||||
"scheb/two-factor-bundle": "^2.14",
|
||||
"scheb/two-factor-bundle": "^3.0",
|
||||
"grandt/phpepub": "dev-master",
|
||||
"wallabag/php-mobi": "~1.0",
|
||||
"kphoen/rulerz-bundle": "~0.13",
|
||||
|
@ -87,7 +87,8 @@
|
|||
"friendsofsymfony/jsrouting-bundle": "^2.2",
|
||||
"bdunogier/guzzle-site-authenticator": "^1.0.0",
|
||||
"defuse/php-encryption": "^2.1",
|
||||
"html2text/html2text": "^4.1"
|
||||
"html2text/html2text": "^4.1",
|
||||
"pragmarx/recovery": "^0.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/doctrine-fixtures-bundle": "~3.0",
|
||||
|
@ -147,7 +148,7 @@
|
|||
"config": {
|
||||
"bin-dir": "bin",
|
||||
"platform": {
|
||||
"php": "7.1"
|
||||
"php": "7.1.3"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
|
|
|
@ -57,7 +57,8 @@ class ShowUserCommand extends ContainerAwareCommand
|
|||
sprintf('Display name: %s', $user->getName()),
|
||||
sprintf('Creation date: %s', $user->getCreatedAt()->format('Y-m-d H:i:s')),
|
||||
sprintf('Last login: %s', null !== $user->getLastLogin() ? $user->getLastLogin()->format('Y-m-d H:i:s') : 'never'),
|
||||
sprintf('2FA activated: %s', $user->isTwoFactorAuthentication() ? 'yes' : 'no'),
|
||||
sprintf('2FA (email) activated: %s', $user->isEmailTwoFactor() ? 'yes' : 'no'),
|
||||
sprintf('2FA (OTP) activated: %s', $user->isGoogleAuthenticatorEnabled() ? 'yes' : 'no'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Wallabag\CoreBundle\Controller;
|
||||
|
||||
use PragmaRX\Recovery\Recovery as BackupCodes;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
@ -46,7 +47,7 @@ class ConfigController extends Controller
|
|||
$activeTheme = $this->get('liip_theme.active_theme');
|
||||
$activeTheme->setName($config->getTheme());
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.config_saved'
|
||||
);
|
||||
|
@ -68,7 +69,7 @@ class ConfigController extends Controller
|
|||
$userManager->updateUser($user, true);
|
||||
}
|
||||
|
||||
$this->get('session')->getFlashBag()->add('notice', $message);
|
||||
$this->addFlash('notice', $message);
|
||||
|
||||
return $this->redirect($this->generateUrl('config') . '#set4');
|
||||
}
|
||||
|
@ -83,7 +84,7 @@ class ConfigController extends Controller
|
|||
if ($userForm->isSubmitted() && $userForm->isValid()) {
|
||||
$userManager->updateUser($user, true);
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.user_updated'
|
||||
);
|
||||
|
@ -99,7 +100,7 @@ class ConfigController extends Controller
|
|||
$em->persist($config);
|
||||
$em->flush();
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.rss_updated'
|
||||
);
|
||||
|
@ -131,7 +132,7 @@ class ConfigController extends Controller
|
|||
$em->persist($taggingRule);
|
||||
$em->flush();
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.tagging_rules_updated'
|
||||
);
|
||||
|
@ -153,11 +154,123 @@ class ConfigController extends Controller
|
|||
],
|
||||
'twofactor_auth' => $this->getParameter('twofactor_auth'),
|
||||
'wallabag_url' => $this->getParameter('domain_name'),
|
||||
'enabled_users' => $this->get('wallabag_user.user_repository')
|
||||
->getSumEnabledUsers(),
|
||||
'enabled_users' => $this->get('wallabag_user.user_repository')->getSumEnabledUsers(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable 2FA using email.
|
||||
*
|
||||
* @Route("/config/otp/email", name="config_otp_email")
|
||||
*/
|
||||
public function otpEmailAction()
|
||||
{
|
||||
if (!$this->getParameter('twofactor_auth')) {
|
||||
return $this->createNotFoundException('two_factor not enabled');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
|
||||
$user->setGoogleAuthenticatorSecret(null);
|
||||
$user->setBackupCodes(null);
|
||||
$user->setEmailTwoFactor(true);
|
||||
|
||||
$this->container->get('fos_user.user_manager')->updateUser($user, true);
|
||||
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.otp_enabled'
|
||||
);
|
||||
|
||||
return $this->redirect($this->generateUrl('config') . '#set3');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable 2FA using OTP app, user will need to confirm the generated code from the app.
|
||||
*
|
||||
* @Route("/config/otp/app", name="config_otp_app")
|
||||
*/
|
||||
public function otpAppAction()
|
||||
{
|
||||
if (!$this->getParameter('twofactor_auth')) {
|
||||
return $this->createNotFoundException('two_factor not enabled');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
$secret = $this->get('scheb_two_factor.security.google_authenticator')->generateSecret();
|
||||
|
||||
$user->setGoogleAuthenticatorSecret($secret);
|
||||
$user->setEmailTwoFactor(false);
|
||||
|
||||
$backupCodes = (new BackupCodes())->toArray();
|
||||
$backupCodesHashed = array_map(
|
||||
function ($backupCode) {
|
||||
return password_hash($backupCode, PASSWORD_DEFAULT);
|
||||
},
|
||||
$backupCodes
|
||||
);
|
||||
|
||||
$user->setBackupCodes($backupCodesHashed);
|
||||
|
||||
$this->container->get('fos_user.user_manager')->updateUser($user, true);
|
||||
|
||||
return $this->render('WallabagCoreBundle:Config:otp_app.html.twig', [
|
||||
'backupCodes' => $backupCodes,
|
||||
'qr_code' => $this->get('scheb_two_factor.security.google_authenticator')->getQRContent($user),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancelling 2FA using OTP app.
|
||||
*
|
||||
* @Route("/config/otp/app/cancel", name="config_otp_app_cancel")
|
||||
*/
|
||||
public function otpAppCancelAction()
|
||||
{
|
||||
if (!$this->getParameter('twofactor_auth')) {
|
||||
return $this->createNotFoundException('two_factor not enabled');
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
$user->setGoogleAuthenticatorSecret(null);
|
||||
$user->setBackupCodes(null);
|
||||
|
||||
$this->container->get('fos_user.user_manager')->updateUser($user, true);
|
||||
|
||||
return $this->redirect($this->generateUrl('config') . '#set3');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate OTP code.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @Route("/config/otp/app/check", name="config_otp_app_check")
|
||||
*/
|
||||
public function otpAppCheckAction(Request $request)
|
||||
{
|
||||
$isValid = $this->get('scheb_two_factor.security.google_authenticator')->checkCode(
|
||||
$this->getUser(),
|
||||
$request->get('_auth_code')
|
||||
);
|
||||
|
||||
if (true === $isValid) {
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.otp_enabled'
|
||||
);
|
||||
|
||||
return $this->redirect($this->generateUrl('config') . '#set3');
|
||||
}
|
||||
|
||||
$this->addFlash(
|
||||
'two_factor',
|
||||
'scheb_two_factor.code_invalid'
|
||||
);
|
||||
|
||||
return $this->redirect($this->generateUrl('config_otp_app'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
|
@ -178,7 +291,7 @@ class ConfigController extends Controller
|
|||
return new JsonResponse(['token' => $config->getRssToken()]);
|
||||
}
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.rss_token_updated'
|
||||
);
|
||||
|
@ -203,7 +316,7 @@ class ConfigController extends Controller
|
|||
$em->remove($rule);
|
||||
$em->flush();
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.tagging_rules_deleted'
|
||||
);
|
||||
|
@ -269,7 +382,7 @@ class ConfigController extends Controller
|
|||
break;
|
||||
}
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
$this->addFlash(
|
||||
'notice',
|
||||
'flashes.config.notice.' . $type . '_reset'
|
||||
);
|
||||
|
|
|
@ -21,9 +21,14 @@ class UserInformationType extends AbstractType
|
|||
->add('email', EmailType::class, [
|
||||
'label' => 'config.form_user.email_label',
|
||||
])
|
||||
->add('twoFactorAuthentication', CheckboxType::class, [
|
||||
->add('emailTwoFactor', CheckboxType::class, [
|
||||
'required' => false,
|
||||
'label' => 'config.form_user.twoFactorAuthentication_label',
|
||||
'label' => 'config.form_user.emailTwoFactor_label',
|
||||
])
|
||||
->add('googleTwoFactor', CheckboxType::class, [
|
||||
'required' => false,
|
||||
'label' => 'config.form_user.googleTwoFactor_label',
|
||||
'mapped' => false,
|
||||
])
|
||||
->add('save', SubmitType::class, [
|
||||
'label' => 'config.form.save',
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Adgangskode'
|
||||
# rules: 'Tagging rules'
|
||||
new_user: 'Tilføj bruger'
|
||||
# reset: 'Reset area'
|
||||
form:
|
||||
save: 'Gem'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,19 @@ config:
|
|||
# all: 'All'
|
||||
# rss_limit: 'Number of items in the feed'
|
||||
form_user:
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connexion"
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Navn'
|
||||
email_label: 'Emailadresse'
|
||||
# twoFactorAuthentication_label: 'Two factor authentication'
|
||||
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
|
||||
two_factor:
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
# title: Delete my account (a.k.a 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.
|
||||
|
@ -160,6 +169,15 @@ config:
|
|||
# and: 'One rule AND another'
|
||||
# matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
|
||||
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
# default_title: 'Title of the entry'
|
||||
|
@ -532,7 +550,8 @@ user:
|
|||
email_label: 'Emailadresse'
|
||||
# enabled_label: 'Enabled'
|
||||
# last_login_label: 'Last login'
|
||||
# twofactor_label: Two factor authentication
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
# save: Save
|
||||
# delete: Delete
|
||||
# delete_confirm: Are you sure?
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Kennwort'
|
||||
rules: 'Tagging-Regeln'
|
||||
new_user: 'Benutzer hinzufügen'
|
||||
reset: 'Zurücksetzen'
|
||||
form:
|
||||
save: 'Speichern'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,19 @@ config:
|
|||
all: 'Alle'
|
||||
rss_limit: 'Anzahl der Einträge pro Feed'
|
||||
form_user:
|
||||
two_factor_description: "Wenn du die Zwei-Faktor-Authentifizierung aktivierst, erhältst du eine E-Mail mit einem Code bei jeder nicht vertrauenswürdigen Verbindung"
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Name'
|
||||
email_label: 'E-Mail-Adresse'
|
||||
twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung'
|
||||
help_twoFactorAuthentication: "Wenn du 2FA aktivierst, wirst du bei jedem Login einen Code per E-Mail bekommen."
|
||||
two_factor:
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
title: 'Lösche mein Konto (a.k.a Gefahrenzone)'
|
||||
description: 'Wenn du dein Konto löschst, werden ALL deine Artikel, ALL deine Tags, ALL deine Anmerkungen und dein Konto dauerhaft gelöscht (kann NICHT RÜCKGÄNGIG gemacht werden). Du wirst anschließend ausgeloggt.'
|
||||
|
@ -532,7 +541,8 @@ user:
|
|||
email_label: 'E-Mail-Adresse'
|
||||
enabled_label: 'Aktiviert'
|
||||
last_login_label: 'Letzter Login'
|
||||
twofactor_label: 'Zwei-Faktor-Authentifizierung'
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
save: 'Speichern'
|
||||
delete: 'Löschen'
|
||||
delete_confirm: 'Bist du sicher?'
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Password'
|
||||
rules: 'Tagging rules'
|
||||
new_user: 'Add a user'
|
||||
reset: 'Reset area'
|
||||
form:
|
||||
save: 'Save'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,19 @@ config:
|
|||
all: 'All'
|
||||
rss_limit: 'Number of items in the feed'
|
||||
form_user:
|
||||
two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connection."
|
||||
two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Name'
|
||||
email_label: 'Email'
|
||||
twoFactorAuthentication_label: 'Two factor authentication'
|
||||
help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
|
||||
two_factor:
|
||||
emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
table_method: Method
|
||||
table_state: State
|
||||
table_action: Action
|
||||
state_enabled: Enabled
|
||||
state_disabled: Disabled
|
||||
action_email: Use email
|
||||
action_app: Use OTP App
|
||||
delete:
|
||||
title: Delete my account (a.k.a 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.
|
||||
|
@ -160,6 +169,15 @@ config:
|
|||
and: 'One rule AND another'
|
||||
matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
|
||||
notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
page_title: Two-factor authentication
|
||||
app:
|
||||
two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
cancel: Cancel
|
||||
enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: 'Title of the entry'
|
||||
|
@ -532,7 +550,8 @@ user:
|
|||
email_label: 'Email'
|
||||
enabled_label: 'Enabled'
|
||||
last_login_label: 'Last login'
|
||||
twofactor_label: Two factor authentication
|
||||
twofactor_email_label: Two factor authentication by email
|
||||
twofactor_google_label: Two factor authentication by OTP app
|
||||
save: Save
|
||||
delete: Delete
|
||||
delete_confirm: Are you sure?
|
||||
|
@ -578,6 +597,7 @@ flashes:
|
|||
tags_reset: Tags reset
|
||||
entries_reset: Entries reset
|
||||
archived_reset: Archived entries deleted
|
||||
otp_enabled: Two-factor authentication enabled
|
||||
entry:
|
||||
notice:
|
||||
entry_already_saved: 'Entry already saved on %date%'
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Contraseña'
|
||||
rules: 'Reglas de etiquetado automáticas'
|
||||
new_user: 'Añadir un usuario'
|
||||
reset: 'Reiniciar mi cuenta'
|
||||
form:
|
||||
save: 'Guardar'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,19 @@ config:
|
|||
# all: 'All'
|
||||
rss_limit: 'Límite de artículos en feed RSS'
|
||||
form_user:
|
||||
two_factor_description: "Con la autenticación en dos pasos recibirá código por e-mail en cada nueva conexión que no sea de confianza."
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Nombre'
|
||||
email_label: 'Dirección de e-mail'
|
||||
twoFactorAuthentication_label: 'Autenticación en dos pasos'
|
||||
help_twoFactorAuthentication: "Si activas la autenticación en dos pasos, cada vez que quieras iniciar sesión en wallabag recibirás un código por e-mail."
|
||||
two_factor:
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
title: Eliminar mi cuenta (Zona peligrosa)
|
||||
description: Si eliminas tu cuenta, TODOS tus artículos, TODAS tus etiquetas, TODAS tus anotaciones y tu cuenta serán eliminadas de forma PERMANENTE (no se puede deshacer). Después serás desconectado.
|
||||
|
@ -160,6 +169,15 @@ config:
|
|||
and: 'Una regla Y la otra'
|
||||
matches: 'Prueba si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>title matches "fútbol"</code>'
|
||||
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: 'Título del artículo'
|
||||
|
@ -532,7 +550,8 @@ user:
|
|||
email_label: 'E-mail'
|
||||
enabled_label: 'Activado'
|
||||
last_login_label: 'Último inicio de sesión'
|
||||
twofactor_label: Autenticación en dos pasos
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
save: Guardar
|
||||
delete: Eliminar
|
||||
delete_confirm: ¿Estás seguro?
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'رمز'
|
||||
rules: 'برچسبگذاری خودکار'
|
||||
new_user: 'افزودن کاربر'
|
||||
# reset: 'Reset area'
|
||||
form:
|
||||
save: 'ذخیره'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,19 @@ config:
|
|||
# all: 'All'
|
||||
rss_limit: 'محدودیت آر-اس-اس'
|
||||
form_user:
|
||||
two_factor_description: "با فعالکردن تأیید ۲مرحلهای هر بار که اتصال تأییدنشدهای برقرار شد، به شما یک کد از راه ایمیل فرستاده میشود"
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'نام'
|
||||
email_label: 'نشانی ایمیل'
|
||||
twoFactorAuthentication_label: 'تأیید ۲مرحلهای'
|
||||
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
|
||||
two_factor:
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
# title: Delete my account (a.k.a 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.
|
||||
|
@ -160,6 +169,15 @@ config:
|
|||
# and: 'One rule AND another'
|
||||
# matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
|
||||
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
# default_title: 'Title of the entry'
|
||||
|
@ -532,7 +550,8 @@ user:
|
|||
email_label: 'نشانی ایمیل'
|
||||
# enabled_label: 'Enabled'
|
||||
# last_login_label: 'Last login'
|
||||
# twofactor_label: Two factor authentication
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
# save: Save
|
||||
# delete: Delete
|
||||
# delete_confirm: Are you sure?
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: "Mot de passe"
|
||||
rules: "Règles de tag automatiques"
|
||||
new_user: "Créer un compte"
|
||||
reset: "Réinitialisation"
|
||||
form:
|
||||
save: "Enregistrer"
|
||||
form_settings:
|
||||
|
@ -98,11 +99,19 @@ config:
|
|||
all: "Tous"
|
||||
rss_limit: "Nombre d’articles dans le flux"
|
||||
form_user:
|
||||
two_factor_description: "Activer l’authentification double-facteur veut dire que vous allez recevoir un code par courriel à chaque nouvelle connexion non approuvée."
|
||||
two_factor_description: "Activer l’authentification double-facteur veut dire que vous allez recevoir un code par courriel OU que vous devriez utiliser une application de mot de passe à usage unique (comme Google Authenticator, Authy or FreeOTP) pour obtenir un code temporaire à chaque nouvelle connexion non approuvée. Vous ne pouvez pas choisir les deux options."
|
||||
name_label: "Nom"
|
||||
email_label: "Adresse courriel"
|
||||
twoFactorAuthentication_label: "Double authentification"
|
||||
help_twoFactorAuthentication: "Si vous activez 2FA, à chaque tentative de connexion à wallabag, vous recevrez un code par email."
|
||||
two_factor:
|
||||
emailTwoFactor_label: 'En utlisant l’email (recevez un code par email)'
|
||||
googleTwoFactor_label: 'En utilisant une application de mot de passe à usage unique (ouvrez l’app, comme Google Authenticator, Authy or FreeOTP, pour obtenir un mot de passe à usage unique)'
|
||||
table_method: Méthode
|
||||
table_state: État
|
||||
table_action: Action
|
||||
state_enabled: Activé
|
||||
state_disabled: Désactivé
|
||||
action_email: Utiliser l'email
|
||||
action_app: Utiliser une app OTP
|
||||
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é."
|
||||
|
@ -160,6 +169,15 @@ config:
|
|||
and: "Une règle ET l’autre"
|
||||
matches: "Teste si un <i>sujet</i> correspond à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title matches \"football\"</code>"
|
||||
notmatches: "Teste si un <i>sujet</i> ne correspond pas à une <i>recherche</i> (non sensible à la casse).<br />Exemple : <code>title notmatches \"football\"</code>"
|
||||
otp:
|
||||
page_title: Authentification double-facteur
|
||||
app:
|
||||
two_factor_code_description_1: Vous venez d’activer l’authentification double-facteur, ouvrez votre application OTP pour configurer la génération du mot de passe à usage unique. Ces informations disparaîtront après un rechargement de la page.
|
||||
two_factor_code_description_2: 'Vous pouvez scanner le QR code avec votre application :'
|
||||
two_factor_code_description_3: 'N’oubliez pas de sauvegarder ces codes de secours dans un endroit sûr, vous pourrez les utiliser si vous ne pouvez plus accéder à votre application OTP :'
|
||||
two_factor_code_description_4: 'Testez un code généré par votre application OTP :'
|
||||
cancel: Annuler
|
||||
enable: Activer
|
||||
|
||||
entry:
|
||||
default_title: "Titre de l’article"
|
||||
|
@ -533,6 +551,8 @@ user:
|
|||
enabled_label: "Activé"
|
||||
last_login_label: "Dernière connexion"
|
||||
twofactor_label: "Double authentification"
|
||||
twofactor_email_label: Double authentification par email
|
||||
twofactor_google_label: Double authentification par OTP app
|
||||
save: "Sauvegarder"
|
||||
delete: "Supprimer"
|
||||
delete_confirm: "Êtes-vous sûr ?"
|
||||
|
@ -578,6 +598,7 @@ flashes:
|
|||
tags_reset: "Tags supprimés"
|
||||
entries_reset: "Articles supprimés"
|
||||
archived_reset: "Articles archivés supprimés"
|
||||
otp_enabled: "Authentification à double-facteur activée"
|
||||
entry:
|
||||
notice:
|
||||
entry_already_saved: "Article déjà sauvegardé le %date%"
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Password'
|
||||
rules: 'Regole di etichettatura'
|
||||
new_user: 'Aggiungi utente'
|
||||
reset: 'Area di reset'
|
||||
form:
|
||||
save: 'Salva'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,18 @@ config:
|
|||
# all: 'All'
|
||||
rss_limit: 'Numero di elementi nel feed'
|
||||
form_user:
|
||||
two_factor_description: "Abilitando l'autenticazione a due fattori riceverai una e-mail con un codice per ogni nuova connesione non verificata"
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Nome'
|
||||
email_label: 'E-mail'
|
||||
twoFactorAuthentication_label: 'Autenticazione a due fattori'
|
||||
help_twoFactorAuthentication: "Se abiliti l'autenticazione a due fattori, ogni volta che vorrai connetterti a wallabag, riceverai un codice via E-mail."
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
title: Cancella il mio account (zona pericolosa)
|
||||
description: Rimuovendo il tuo account, TUTTI i tuoi articoli, TUTTE le tue etichette, TUTTE le tue annotazioni ed il tuo account verranno rimossi PERMANENTEMENTE (impossibile da ANNULLARE). Verrai poi disconnesso.
|
||||
|
@ -160,6 +168,15 @@ config:
|
|||
and: "Una regola E un'altra"
|
||||
matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>'
|
||||
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: "Titolo del contenuto"
|
||||
|
@ -532,7 +549,8 @@ user:
|
|||
email_label: 'E-mail'
|
||||
enabled_label: 'Abilitato'
|
||||
last_login_label: 'Ultima connessione'
|
||||
twofactor_label: Autenticazione a due fattori
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
save: Salva
|
||||
delete: Cancella
|
||||
delete_confirm: Sei sicuro?
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Senhal'
|
||||
rules: "Règlas d'etiquetas automaticas"
|
||||
new_user: 'Crear un compte'
|
||||
reset: 'Zòna de reïnicializacion'
|
||||
form:
|
||||
save: 'Enregistrar'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,18 @@ config:
|
|||
all: 'Totes'
|
||||
rss_limit: "Nombre d'articles dins un flux RSS"
|
||||
form_user:
|
||||
two_factor_description: "Activar l'autentificacion en dos temps vòl dire que recebretz un còdi per corrièl per cada novèla connexion pas aprovada."
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Nom'
|
||||
email_label: 'Adreça de corrièl'
|
||||
twoFactorAuthentication_label: 'Dobla autentificacion'
|
||||
help_twoFactorAuthentication: "S'avètz activat l'autentificacion en dos temps, cada còp que volètz vos connectar a wallabag, recebretz un còdi per corrièl."
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
title: Suprimir mon compte (Mèfi zòna perilhosa)
|
||||
description: Se confirmatz la supression de vòstre compte, TOTES vòstres articles, TOTAS vòstras etiquetas, TOTAS vòstras anotacions e vòstre compte seràn suprimits per totjorn. E aquò es IRREVERSIBLE. Puèi seretz desconnectat.
|
||||
|
@ -160,6 +168,15 @@ config:
|
|||
and: "Una règla E l'autra"
|
||||
matches: 'Teste se un <i>subjècte</i> correspond a una <i>recèrca</i> (non sensibla a la cassa).<br />Exemple : <code>title matches \"football\"</code>'
|
||||
notmatches: 'Teste se <i>subjècte</i> correspond pas a una <i>recèrca</i> (sensibla a la cassa).<br />Example : <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: "Títol de l'article"
|
||||
|
@ -532,7 +549,8 @@ user:
|
|||
email_label: 'Adreça de corrièl'
|
||||
enabled_label: 'Actiu'
|
||||
last_login_label: 'Darrièra connexion'
|
||||
twofactor_label: 'Autentificacion doble-factor'
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
save: 'Enregistrar'
|
||||
delete: 'Suprimir'
|
||||
delete_confirm: 'Sètz segur ?'
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Hasło'
|
||||
rules: 'Zasady tagowania'
|
||||
new_user: 'Dodaj użytkownika'
|
||||
reset: 'Reset'
|
||||
form:
|
||||
save: 'Zapisz'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,18 @@ config:
|
|||
all: 'Wszystkie'
|
||||
rss_limit: 'Link do RSS'
|
||||
form_user:
|
||||
two_factor_description: "Włączenie autoryzacji dwuetapowej oznacza, że będziesz otrzymywał maile z kodem przy każdym nowym, niezaufanym połączeniu"
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Nazwa'
|
||||
email_label: 'Adres email'
|
||||
twoFactorAuthentication_label: 'Autoryzacja dwuetapowa'
|
||||
help_twoFactorAuthentication: "Jeżeli włączysz autoryzację dwuetapową. Za każdym razem, kiedy będziesz chciał się zalogować, dostaniesz kod na swój e-mail."
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
title: Usuń moje konto (niebezpieczna strefa !)
|
||||
description: Jeżeli usuniesz swoje konto, wszystkie twoje artykuły, tagi, adnotacje, oraz konto zostaną trwale usunięte (operacja jest NIEODWRACALNA). Następnie zostaniesz wylogowany.
|
||||
|
@ -160,6 +168,15 @@ config:
|
|||
and: 'Jedna reguła I inna'
|
||||
matches: 'Sprawdź czy <i>temat</i> pasuje <i>szukaj</i> (duże lub małe litery).<br />Przykład: <code>tytuł zawiera "piłka nożna"</code>'
|
||||
notmatches: 'Sprawdź czy <i>temat</i> nie zawiera <i>szukaj</i> (duże lub małe litery).<br />Przykład: <code>tytuł nie zawiera "piłka nożna"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: 'Tytuł wpisu'
|
||||
|
@ -532,7 +549,8 @@ user:
|
|||
email_label: 'Adres email'
|
||||
enabled_label: 'Włączony'
|
||||
last_login_label: 'Ostatnie logowanie'
|
||||
twofactor_label: Autoryzacja dwuetapowa
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
save: Zapisz
|
||||
delete: Usuń
|
||||
delete_confirm: Jesteś pewien?
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Senha'
|
||||
rules: 'Regras de tags'
|
||||
new_user: 'Adicionar um usuário'
|
||||
# reset: 'Reset area'
|
||||
form:
|
||||
save: 'Salvar'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,18 @@ config:
|
|||
# all: 'All'
|
||||
rss_limit: 'Número de itens no feed'
|
||||
form_user:
|
||||
two_factor_description: 'Habilitar autenticação de dois passos significa que você receberá um e-mail com um código a cada nova conexão desconhecida.'
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Nome'
|
||||
email_label: 'E-mail'
|
||||
twoFactorAuthentication_label: 'Autenticação de dois passos'
|
||||
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
# title: Delete my account (a.k.a 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.
|
||||
|
@ -160,6 +168,15 @@ config:
|
|||
and: 'Uma regra E outra'
|
||||
matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>'
|
||||
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: 'Título da entrada'
|
||||
|
@ -532,7 +549,8 @@ user:
|
|||
email_label: 'E-mail'
|
||||
enabled_label: 'Habilitado'
|
||||
last_login_label: 'Último login'
|
||||
twofactor_label: 'Autenticação de dois passos'
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
save: 'Salvar'
|
||||
delete: 'Apagar'
|
||||
delete_confirm: 'Tem certeza?'
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Parolă'
|
||||
# rules: 'Tagging rules'
|
||||
new_user: 'Crează un utilizator'
|
||||
# reset: 'Reset area'
|
||||
form:
|
||||
save: 'Salvează'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,18 @@ config:
|
|||
# all: 'All'
|
||||
rss_limit: 'Limită RSS'
|
||||
form_user:
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code on every new untrusted connexion"
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Nume'
|
||||
email_label: 'E-mail'
|
||||
# twoFactorAuthentication_label: 'Two factor authentication'
|
||||
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
# title: Delete my account (a.k.a 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.
|
||||
|
@ -160,6 +168,15 @@ config:
|
|||
# and: 'One rule AND another'
|
||||
# matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
|
||||
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
# default_title: 'Title of the entry'
|
||||
|
@ -532,7 +549,8 @@ user:
|
|||
email_label: 'E-mail'
|
||||
# enabled_label: 'Enabled'
|
||||
# last_login_label: 'Last login'
|
||||
# twofactor_label: Two factor authentication
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
# save: Save
|
||||
# delete: Delete
|
||||
# delete_confirm: Are you sure?
|
||||
|
|
|
@ -58,6 +58,7 @@ config:
|
|||
password: 'Пароль'
|
||||
rules: 'Правила настройки простановки тегов'
|
||||
new_user: 'Добавить пользователя'
|
||||
reset: 'Сброс данных'
|
||||
form:
|
||||
save: 'Сохранить'
|
||||
form_settings:
|
||||
|
@ -95,11 +96,18 @@ config:
|
|||
archive: 'архивные'
|
||||
rss_limit: 'Количество записей в фиде'
|
||||
form_user:
|
||||
two_factor_description: "Включить двухфакторную аутентификацию, Вы получите сообщение на указанный email с кодом, при каждом новом непроверенном подключении."
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'Имя'
|
||||
email_label: 'Email'
|
||||
twoFactorAuthentication_label: 'Двухфакторная аутентификация'
|
||||
help_twoFactorAuthentication: "Если Вы включите двухфакторную аутентификацию, то Вы будете получать код на указанный ранее email, каждый раз при входе в wallabag."
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
title: "Удалить мой аккаунт (или опасная зона)"
|
||||
description: "Если Вы удалите ваш аккаунт, ВСЕ ваши записи, теги и другие данные, будут БЕЗВОЗВРАТНО удалены (операция не может быть отменена после). Затем Вы выйдете из системы."
|
||||
|
@ -155,6 +163,15 @@ config:
|
|||
or: 'Одно правило ИЛИ другое'
|
||||
and: 'Одно правило И другое'
|
||||
matches: 'Тесты, в которых <i> тема </i> соответствует <i> поиску </i> (без учета регистра). Пример: <code> title matches "футбол" </code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: 'Название записи'
|
||||
|
@ -520,7 +537,8 @@ user:
|
|||
email_label: 'Email'
|
||||
enabled_label: 'Включить'
|
||||
last_login_label: 'Последний вход'
|
||||
twofactor_label: "Двухфакторная аутентификация"
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
save: "Сохранить"
|
||||
delete: "Удалить"
|
||||
delete_confirm: "Вы уверены?"
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'รหัสผ่าน'
|
||||
rules: 'การแท็กข้อบังคับ'
|
||||
new_user: 'เพิ่มผู้ใช้'
|
||||
reset: 'รีเซ็ตพื้นที่ '
|
||||
form:
|
||||
save: 'บันทึก'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,18 @@ config:
|
|||
all: 'ทั้งหมด'
|
||||
rss_limit: 'จำนวนไอเทมที่เก็บ'
|
||||
form_user:
|
||||
two_factor_description: "การเปิดใช้งาน two factor authentication คือคุณจะต้องได้รับอีเมลกับ code ที่ยังไม่ตรวจสอบในการเชื่อมต่อ"
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'ชื่อ'
|
||||
email_label: 'อีเมล'
|
||||
twoFactorAuthentication_label: 'Two factor authentication'
|
||||
help_twoFactorAuthentication: "ถ้าคุณเปิด 2FA, ในแต่ละช่วงเวลาที่คุณต้องการลงชื่อเข้าใช wallabag, คุณจะต้องได้รับ code จากอีเมล"
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
title: ลบบัญชีของฉัน (โซนที่เป็นภัย!)
|
||||
description: ถ้าคุณลบบัญชีของคุณIf , รายการทั้งหมดของคุณ, แท็กทั้งหมดของคุณ, หมายเหตุทั้งหมดของคุณและบัญชีของคุณจะถูกลบอย่างถาวร (มันไม่สามารถยกเลิกได้) คุณจะต้องลงชื่อออก
|
||||
|
@ -160,6 +168,15 @@ config:
|
|||
and: 'หนึ่งข้อบังคับและอื่นๆ'
|
||||
matches: 'ทดสอบว่า <i>เรื่อง</i> นี้ตรงกับ <i>การต้นหา</i> (กรณีไม่ทราบ).<br />ตัวอย่าง: <code>หัวข้อที่ตรงกับ "football"</code>'
|
||||
notmatches: 'ทดสอบว่า <i>เรื่อง</i> นี้ไม่ตรงกับ <i>การต้นหา</i> (กรณีไม่ทราบ).<br />ตัวอย่าง: <code>หัวข้อทีไม่ตรงกับ "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: 'หัวข้อรายการ'
|
||||
|
@ -530,7 +547,8 @@ user:
|
|||
email_label: 'อีเมล'
|
||||
enabled_label: 'เปิดใช้งาน'
|
||||
last_login_label: 'ลงชื้อเข้าใช้ครั้งสุดท้าย'
|
||||
twofactor_label: Two factor authentication
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
save: บันทึก
|
||||
delete: ลบ
|
||||
delete_confirm: ตุณแน่ใจหรือไม่?
|
||||
|
|
|
@ -59,6 +59,7 @@ config:
|
|||
password: 'Şifre'
|
||||
rules: 'Etiketleme kuralları'
|
||||
new_user: 'Bir kullanıcı ekle'
|
||||
# reset: 'Reset area'
|
||||
form:
|
||||
save: 'Kaydet'
|
||||
form_settings:
|
||||
|
@ -98,11 +99,18 @@ config:
|
|||
# all: 'All'
|
||||
rss_limit: 'RSS içeriğinden talep edilecek makale limiti'
|
||||
form_user:
|
||||
two_factor_description: "İki adımlı doğrulamayı aktifleştirdiğinizde, her yeni güvenilmeyen bağlantılarda size e-posta ile bir kod alacaksınız."
|
||||
# two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option."
|
||||
name_label: 'İsim'
|
||||
email_label: 'E-posta'
|
||||
twoFactorAuthentication_label: 'İki adımlı doğrulama'
|
||||
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
|
||||
# emailTwoFactor_label: 'Using email (receive a code by email)'
|
||||
# googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)'
|
||||
# table_method: Method
|
||||
# table_state: State
|
||||
# table_action: Action
|
||||
# state_enabled: Enabled
|
||||
# state_disabled: Disabled
|
||||
# action_email: Use email
|
||||
# action_app: Use OTP App
|
||||
delete:
|
||||
# title: Delete my account (a.k.a 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.
|
||||
|
@ -160,6 +168,15 @@ config:
|
|||
and: 'Bir kural ve diğeri'
|
||||
# matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
|
||||
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
|
||||
otp:
|
||||
# page_title: Two-factor authentication
|
||||
# app:
|
||||
# two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload.
|
||||
# two_factor_code_description_2: 'You can scan that QR Code with your app:'
|
||||
# two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:'
|
||||
# two_factor_code_description_4: 'Test an OTP code from your configured app:'
|
||||
# cancel: Cancel
|
||||
# enable: Enable
|
||||
|
||||
entry:
|
||||
default_title: 'Makalenin başlığı'
|
||||
|
@ -530,7 +547,8 @@ user:
|
|||
email_label: 'E-posta'
|
||||
# enabled_label: 'Enabled'
|
||||
# last_login_label: 'Last login'
|
||||
# twofactor_label: Two factor authentication
|
||||
# twofactor_email_label: Two factor authentication by email
|
||||
# twofactor_google_label: Two factor authentication by OTP app
|
||||
# save: Save
|
||||
# delete: Delete
|
||||
# delete_confirm: Are you sure?
|
||||
|
|
|
@ -86,8 +86,7 @@
|
|||
<br/>
|
||||
<img id="androidQrcode" />
|
||||
<script>
|
||||
const imgBase64 = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}');
|
||||
document.getElementById('androidQrcode').src = imgBase64;
|
||||
document.getElementById('androidQrcode').src = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}');
|
||||
</script>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
@ -169,52 +168,41 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
{{ form_widget(form.user.save) }}
|
||||
|
||||
{% if twofactor_auth %}
|
||||
<h5>{{ 'config.otp.page_title'|trans }}</h5>
|
||||
|
||||
<div class="row">
|
||||
{{ 'config.form_user.two_factor_description'|trans }}
|
||||
</div>
|
||||
|
||||
<fieldset class="w500p inline">
|
||||
<div class="row">
|
||||
{{ form_label(form.user.twoFactorAuthentication) }}
|
||||
{{ form_errors(form.user.twoFactorAuthentication) }}
|
||||
{{ form_widget(form.user.twoFactorAuthentication) }}
|
||||
</div>
|
||||
<a href="#" title="{{ 'config.form_user.help_twoFactorAuthentication'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</fieldset>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'config.form_user.two_factor.table_method'|trans }}</th>
|
||||
<th>{{ 'config.form_user.two_factor.table_state'|trans }}</th>
|
||||
<th>{{ 'config.form_user.two_factor.table_action'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td>
|
||||
<td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
|
||||
<td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td>
|
||||
<td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
|
||||
<td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<h2>{{ 'config.reset.title'|trans }}</h2>
|
||||
<fieldset class="w500p inline">
|
||||
<p>{{ 'config.reset.description'|trans }}</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.annotations'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.tags'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.archived'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.entries'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
{{ form_widget(form.user._token) }}
|
||||
{{ form_widget(form.user.save) }}
|
||||
</form>
|
||||
|
||||
{% if enabled_users > 1 %}
|
||||
|
@ -277,7 +265,7 @@
|
|||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{{ form_start(form.new_tagging_rule) }}
|
||||
{{ form_start(form.new_tagging_rule) }}
|
||||
{{ form_errors(form.new_tagging_rule) }}
|
||||
|
||||
<fieldset class="w500p inline">
|
||||
|
@ -382,4 +370,31 @@
|
|||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>{{ 'config.reset.title'|trans }}</h2>
|
||||
<fieldset class="w500p inline">
|
||||
<p>{{ 'config.reset.description'|trans }}</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.annotations'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.tags'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.archived'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.entries'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
{% extends "WallabagCoreBundle::layout.html.twig" %}
|
||||
|
||||
{% block title %}{{ 'config.page_title'|trans }} > {{ 'config.otp.page_title'|trans }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h5>{{ 'config.otp.page_title'|trans }}</h5>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_1'|trans }}</p>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p>
|
||||
|
||||
<p>
|
||||
<img id="2faQrcode" class="hide-on-med-and-down" />
|
||||
<script>
|
||||
document.getElementById('2faQrcode').src = jrQrcode.getQrBase64('{{ qr_code }}');
|
||||
</script>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p>
|
||||
|
||||
<p><strong>{{ backupCodes|join("\n")|nl2br }}</strong></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p>
|
||||
|
||||
{% for flashMessage in app.session.flashbag.get("two_factor") %}
|
||||
<div class="card-panel red darken-1 black-text">
|
||||
{{ flashMessage|trans }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<form class="form" action="{{ path("config_otp_app_check") }}" method="post">
|
||||
<div class="card-content">
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
<label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
|
||||
<input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a href="{{ path('config_otp_app_cancel') }}" class="waves-effect waves-light grey btn">
|
||||
{{ 'config.otp.app.cancel'|trans }}
|
||||
</a>
|
||||
<button class="btn waves-effect waves-light" type="submit" name="send">
|
||||
{{ 'config.otp.app.enable'|trans }}
|
||||
<i class="material-icons right">send</i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
</ol>
|
||||
{% endblock %}
|
|
@ -16,6 +16,7 @@
|
|||
<li class="tab col s12 m6 l3"><a href="#set3">{{ 'config.tab_menu.user_info'|trans }}</a></li>
|
||||
<li class="tab col s12 m6 l3"><a href="#set4">{{ 'config.tab_menu.password'|trans }}</a></li>
|
||||
<li class="tab col s12 m6 l3"><a href="#set5">{{ 'config.tab_menu.rules'|trans }}</a></li>
|
||||
<li class="tab col s12 m6 l3"><a href="#set6">{{ 'config.tab_menu.reset'|trans }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
@ -111,8 +112,7 @@
|
|||
<img id="androidQrcode" class="hide-on-med-and-down" />
|
||||
</div>
|
||||
<script>
|
||||
const imgBase64 = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}');
|
||||
document.getElementById('androidQrcode').src = imgBase64;
|
||||
document.getElementById('androidQrcode').src = jrQrcode.getQrBase64('wallabag://{{ app.user.username }}@{{ wallabag_url }}');
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
@ -196,59 +196,42 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% if twofactor_auth %}
|
||||
<div class="row">
|
||||
<div class="input-field col s11">
|
||||
{{ 'config.form_user.two_factor_description'|trans }}
|
||||
|
||||
<br />
|
||||
|
||||
{{ form_widget(form.user.twoFactorAuthentication) }}
|
||||
{{ form_label(form.user.twoFactorAuthentication) }}
|
||||
{{ form_errors(form.user.twoFactorAuthentication) }}
|
||||
</div>
|
||||
<div class="input-field col s1">
|
||||
<a href="#" class="tooltipped" data-position="left" data-delay="50" data-tooltip="{{ 'config.form_user.help_twoFactorAuthentication'|trans }}">
|
||||
<i class="material-icons">live_help</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
|
||||
|
||||
{% if twofactor_auth %}
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<h5>{{ 'config.otp.page_title'|trans }}</h5>
|
||||
|
||||
<p>{{ 'config.form_user.two_factor_description'|trans }}</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'config.form_user.two_factor.table_method'|trans }}</th>
|
||||
<th>{{ 'config.form_user.two_factor.table_state'|trans }}</th>
|
||||
<th>{{ 'config.form_user.two_factor.table_action'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td>
|
||||
<td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
|
||||
<td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td>
|
||||
<td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
|
||||
<td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ form_widget(form.user._token) }}
|
||||
</form>
|
||||
|
||||
<br /><hr /><br />
|
||||
|
||||
<div class="row">
|
||||
<h5>{{ 'config.reset.title'|trans }}</h5>
|
||||
<p>{{ 'config.reset.description'|trans }}</p>
|
||||
<a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.annotations'|trans }}
|
||||
</a>
|
||||
<a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.tags'|trans }}
|
||||
</a>
|
||||
<a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.archived'|trans }}
|
||||
</a>
|
||||
<a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.entries'|trans }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% 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">
|
||||
|
@ -422,6 +405,37 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="set6" class="col s12">
|
||||
<div class="row">
|
||||
<h5>{{ 'config.reset.title'|trans }}</h5>
|
||||
<p>{{ 'config.reset.description'|trans }}</p>
|
||||
<a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.annotations'|trans }}
|
||||
</a>
|
||||
<a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.tags'|trans }}
|
||||
</a>
|
||||
<a href="{{ path('config_reset', { type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.archived'|trans }}
|
||||
</a>
|
||||
<a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
|
||||
{{ 'config.reset.entries'|trans }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% 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>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
{% extends "WallabagCoreBundle::layout.html.twig" %}
|
||||
|
||||
{% block title %}{{ 'config.page_title'|trans }} > {{ 'config.otp.page_title'|trans }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
<div class="card-panel settings">
|
||||
<div class="row">
|
||||
<h5>{{ 'config.otp.page_title'|trans }}</h5>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_1'|trans }}</p>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_2'|trans }}</p>
|
||||
|
||||
<p>
|
||||
<img id="2faQrcode" class="hide-on-med-and-down" />
|
||||
<script>
|
||||
document.getElementById('2faQrcode').src = jrQrcode.getQrBase64('{{ qr_code }}');
|
||||
</script>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_3'|trans }}</p>
|
||||
|
||||
<p><strong>{{ backupCodes|join("\n")|nl2br }}</strong></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>{{ 'config.otp.app.two_factor_code_description_4'|trans }}</p>
|
||||
|
||||
{% for flashMessage in app.session.flashbag.get("two_factor") %}
|
||||
<div class="card-panel red darken-1 black-text">
|
||||
{{ flashMessage|trans }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<form class="form" action="{{ path("config_otp_app_check") }}" method="post">
|
||||
<div class="card-content">
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
<label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
|
||||
<input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a href="{{ path('config_otp_app_cancel') }}" class="waves-effect waves-light grey btn">
|
||||
{{ 'config.otp.app.cancel'|trans }}
|
||||
</a>
|
||||
<button class="btn waves-effect waves-light" type="submit" name="send">
|
||||
{{ 'config.otp.app.enable'|trans }}
|
||||
<i class="material-icons right">send</i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -62,14 +62,29 @@ class ManageController extends Controller
|
|||
*/
|
||||
public function editAction(Request $request, User $user)
|
||||
{
|
||||
$deleteForm = $this->createDeleteForm($user);
|
||||
$editForm = $this->createForm('Wallabag\UserBundle\Form\UserType', $user);
|
||||
$editForm->handleRequest($request);
|
||||
$userManager = $this->container->get('fos_user.user_manager');
|
||||
|
||||
if ($editForm->isSubmitted() && $editForm->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
$deleteForm = $this->createDeleteForm($user);
|
||||
$form = $this->createForm('Wallabag\UserBundle\Form\UserType', $user);
|
||||
$form->handleRequest($request);
|
||||
|
||||
// `googleTwoFactor` isn't a field within the User entity, we need to define it's value in a different way
|
||||
if ($this->getParameter('twofactor_auth') && true === $user->isGoogleAuthenticatorEnabled() && false === $form->isSubmitted()) {
|
||||
$form->get('googleTwoFactor')->setData(true);
|
||||
}
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
// handle creation / reset of the OTP secret if checkbox changed from the previous state
|
||||
if ($this->getParameter('twofactor_auth')) {
|
||||
if (true === $form->get('googleTwoFactor')->getData() && false === $user->isGoogleAuthenticatorEnabled()) {
|
||||
$user->setGoogleAuthenticatorSecret($this->get('scheb_two_factor.security.google_authenticator')->generateSecret());
|
||||
$user->setEmailTwoFactor(false);
|
||||
} elseif (false === $form->get('googleTwoFactor')->getData() && true === $user->isGoogleAuthenticatorEnabled()) {
|
||||
$user->setGoogleAuthenticatorSecret(null);
|
||||
}
|
||||
}
|
||||
|
||||
$userManager->updateUser($user);
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
'notice',
|
||||
|
@ -81,7 +96,7 @@ class ManageController extends Controller
|
|||
|
||||
return $this->render('WallabagUserBundle:Manage:edit.html.twig', [
|
||||
'user' => $user,
|
||||
'edit_form' => $editForm->createView(),
|
||||
'edit_form' => $form->createView(),
|
||||
'delete_form' => $deleteForm->createView(),
|
||||
'twofactor_auth' => $this->getParameter('twofactor_auth'),
|
||||
]);
|
||||
|
@ -131,8 +146,6 @@ class ManageController extends Controller
|
|||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->get('logger')->info('searching users');
|
||||
|
||||
$searchTerm = (isset($request->get('search_user')['term']) ? $request->get('search_user')['term'] : '');
|
||||
|
||||
$qb = $em->getRepository('WallabagUserBundle:User')->getQueryBuilderForSearch($searchTerm);
|
||||
|
@ -157,7 +170,7 @@ class ManageController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a form to delete a User entity.
|
||||
* Create a form to delete a User entity.
|
||||
*
|
||||
* @param User $user The User entity
|
||||
*
|
||||
|
|
|
@ -8,8 +8,9 @@ use FOS\UserBundle\Model\User as BaseUser;
|
|||
use JMS\Serializer\Annotation\Accessor;
|
||||
use JMS\Serializer\Annotation\Groups;
|
||||
use JMS\Serializer\Annotation\XmlRoot;
|
||||
use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface;
|
||||
use Scheb\TwoFactorBundle\Model\TrustedComputerInterface;
|
||||
use Scheb\TwoFactorBundle\Model\BackupCodeInterface;
|
||||
use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface as EmailTwoFactorInterface;
|
||||
use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface as GoogleTwoFactorInterface;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Wallabag\ApiBundle\Entity\Client;
|
||||
|
@ -28,7 +29,7 @@ use Wallabag\CoreBundle\Helper\EntityTimestampsTrait;
|
|||
* @UniqueEntity("email")
|
||||
* @UniqueEntity("username")
|
||||
*/
|
||||
class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface
|
||||
class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorInterface, BackupCodeInterface
|
||||
{
|
||||
use EntityTimestampsTrait;
|
||||
|
||||
|
@ -123,16 +124,21 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
|
|||
private $authCode;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
* @ORM\Column(name="googleAuthenticatorSecret", type="string", nullable=true)
|
||||
*/
|
||||
private $twoFactorAuthentication = false;
|
||||
private $googleAuthenticatorSecret;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json_array", nullable=true)
|
||||
*/
|
||||
private $trusted;
|
||||
private $backupCodes;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $emailTwoFactor = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -233,49 +239,119 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
|
|||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isTwoFactorAuthentication()
|
||||
public function isEmailTwoFactor()
|
||||
{
|
||||
return $this->twoFactorAuthentication;
|
||||
return $this->emailTwoFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $twoFactorAuthentication
|
||||
* @param bool $emailTwoFactor
|
||||
*/
|
||||
public function setTwoFactorAuthentication($twoFactorAuthentication)
|
||||
public function setEmailTwoFactor($emailTwoFactor)
|
||||
{
|
||||
$this->twoFactorAuthentication = $twoFactorAuthentication;
|
||||
$this->emailTwoFactor = $emailTwoFactor;
|
||||
}
|
||||
|
||||
public function isEmailAuthEnabled()
|
||||
/**
|
||||
* Used in the user config form to be "like" the email option.
|
||||
*/
|
||||
public function isGoogleTwoFactor()
|
||||
{
|
||||
return $this->twoFactorAuthentication;
|
||||
return $this->isGoogleAuthenticatorEnabled();
|
||||
}
|
||||
|
||||
public function getEmailAuthCode()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEmailAuthEnabled(): bool
|
||||
{
|
||||
return $this->emailTwoFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEmailAuthCode(): string
|
||||
{
|
||||
return $this->authCode;
|
||||
}
|
||||
|
||||
public function setEmailAuthCode($authCode)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setEmailAuthCode(string $authCode): void
|
||||
{
|
||||
$this->authCode = $authCode;
|
||||
}
|
||||
|
||||
public function addTrustedComputer($token, \DateTime $validUntil)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEmailAuthRecipient(): string
|
||||
{
|
||||
$this->trusted[$token] = $validUntil->format('r');
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function isTrustedComputer($token)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isGoogleAuthenticatorEnabled(): bool
|
||||
{
|
||||
if (isset($this->trusted[$token])) {
|
||||
$now = new \DateTime();
|
||||
$validUntil = new \DateTime($this->trusted[$token]);
|
||||
return $this->googleAuthenticatorSecret ? true : false;
|
||||
}
|
||||
|
||||
return $now < $validUntil;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGoogleAuthenticatorUsername(): string
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGoogleAuthenticatorSecret(): string
|
||||
{
|
||||
return $this->googleAuthenticatorSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setGoogleAuthenticatorSecret(?string $googleAuthenticatorSecret): void
|
||||
{
|
||||
$this->googleAuthenticatorSecret = $googleAuthenticatorSecret;
|
||||
}
|
||||
|
||||
public function setBackupCodes(array $codes = null)
|
||||
{
|
||||
$this->backupCodes = $codes;
|
||||
}
|
||||
|
||||
public function getBackupCodes()
|
||||
{
|
||||
return $this->backupCodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isBackupCode(string $code): bool
|
||||
{
|
||||
return false === $this->findBackupCode($code) ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function invalidateBackupCode(string $code): void
|
||||
{
|
||||
$key = $this->findBackupCode($code);
|
||||
|
||||
if (false !== $key) {
|
||||
unset($this->backupCodes[$key]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -309,4 +385,24 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf
|
|||
return $this->clients->first();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a backup code from the list of backup codes of the current user.
|
||||
*
|
||||
* @param string $code Given code from the user
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
private function findBackupCode(string $code)
|
||||
{
|
||||
foreach ($this->backupCodes as $key => $backupCode) {
|
||||
// backup code are hashed using `password_hash`
|
||||
// see ConfigController->otpAppAction
|
||||
if (password_verify($code, $backupCode)) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,9 +35,14 @@ class UserType extends AbstractType
|
|||
'required' => false,
|
||||
'label' => 'user.form.enabled_label',
|
||||
])
|
||||
->add('twoFactorAuthentication', CheckboxType::class, [
|
||||
->add('emailTwoFactor', CheckboxType::class, [
|
||||
'required' => false,
|
||||
'label' => 'user.form.twofactor_label',
|
||||
'label' => 'user.form.twofactor_email_label',
|
||||
])
|
||||
->add('googleTwoFactor', CheckboxType::class, [
|
||||
'required' => false,
|
||||
'label' => 'user.form.twofactor_google_label',
|
||||
'mapped' => false,
|
||||
])
|
||||
->add('save', SubmitType::class, [
|
||||
'label' => 'user.form.save',
|
||||
|
|
|
@ -78,7 +78,7 @@ class AuthCodeMailer implements AuthCodeMailerInterface
|
|||
*
|
||||
* @param TwoFactorInterface $user
|
||||
*/
|
||||
public function sendAuthCode(TwoFactorInterface $user)
|
||||
public function sendAuthCode(TwoFactorInterface $user): void
|
||||
{
|
||||
$template = $this->twig->loadTemplate('WallabagUserBundle:TwoFactor:email_auth_code.html.twig');
|
||||
|
||||
|
@ -97,7 +97,7 @@ class AuthCodeMailer implements AuthCodeMailerInterface
|
|||
|
||||
$message = new \Swift_Message();
|
||||
$message
|
||||
->setTo($user->getEmail())
|
||||
->setTo($user->getEmailAuthRecipient())
|
||||
->setFrom($this->senderEmail, $this->senderName)
|
||||
->setSubject($subject)
|
||||
->setBody($bodyText, 'text/plain')
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{# Override `vendor/scheb/two-factor-bundle/Resources/views/Authentication/form.html.twig` #}
|
||||
{% extends "WallabagUserBundle::layout.html.twig" %}
|
||||
|
||||
{% block fos_user_content %}
|
||||
<form class="form" action="" method="post">
|
||||
<form class="form" action="{{ path("2fa_login_check") }}" method="post">
|
||||
<div class="card-content">
|
||||
<div class="row">
|
||||
|
||||
|
@ -9,14 +10,19 @@
|
|||
<p class="error">{{ flashMessage|trans }}</p>
|
||||
{% endfor %}
|
||||
|
||||
{# Authentication errors #}
|
||||
{% if authenticationError %}
|
||||
<p class="error">{{ authenticationError|trans(authenticationErrorData) }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="input-field col s12">
|
||||
<label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
|
||||
<input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
|
||||
<input id="_auth_code" type="text" autocomplete="off" name="{{ authCodeParameterName }}" />
|
||||
</div>
|
||||
|
||||
{% if useTrustedOption %}
|
||||
{% if displayTrustedOption %}
|
||||
<div class="input-field col s12">
|
||||
<input id="_trusted" type="checkbox" name="_trusted" />
|
||||
<input id="_trusted" type="checkbox" name="{{ trustedParameterName }}" />
|
||||
<label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -50,9 +50,14 @@
|
|||
{% if twofactor_auth %}
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
{{ form_widget(edit_form.twoFactorAuthentication) }}
|
||||
{{ form_label(edit_form.twoFactorAuthentication) }}
|
||||
{{ form_errors(edit_form.twoFactorAuthentication) }}
|
||||
{{ form_widget(edit_form.emailTwoFactor) }}
|
||||
{{ form_label(edit_form.emailTwoFactor) }}
|
||||
{{ form_errors(edit_form.emailTwoFactor) }}
|
||||
</div>
|
||||
<div class="input-field col s12">
|
||||
{{ form_widget(edit_form.googleTwoFactor) }}
|
||||
{{ form_label(edit_form.googleTwoFactor) }}
|
||||
{{ form_errors(edit_form.googleTwoFactor) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -59,7 +59,8 @@ class ShowUserCommandTest extends WallabagCoreTestCase
|
|||
$this->assertContains('Username: admin', $tester->getDisplay());
|
||||
$this->assertContains('Email: bigboss@wallabag.org', $tester->getDisplay());
|
||||
$this->assertContains('Display name: Big boss', $tester->getDisplay());
|
||||
$this->assertContains('2FA activated: no', $tester->getDisplay());
|
||||
$this->assertContains('2FA (email) activated', $tester->getDisplay());
|
||||
$this->assertContains('2FA (OTP) activated', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testShowUser()
|
||||
|
|
|
@ -1000,4 +1000,85 @@ class ConfigControllerTest extends WallabagCoreTestCase
|
|||
$this->assertNotSame('yuyuyuyu', $client->getRequest()->getLocale());
|
||||
$this->assertNotSame('yuyuyuyu', $client->getContainer()->get('session')->get('_locale'));
|
||||
}
|
||||
|
||||
public function testUserEnable2faEmail()
|
||||
{
|
||||
$this->logInAs('admin');
|
||||
$client = $this->getClient();
|
||||
|
||||
$crawler = $client->request('GET', '/config/otp/email');
|
||||
|
||||
$this->assertSame(302, $client->getResponse()->getStatusCode());
|
||||
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
$this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
|
||||
$this->assertContains('flashes.config.notice.otp_enabled', $alert[0]);
|
||||
|
||||
// restore user
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em
|
||||
->getRepository('WallabagUserBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
|
||||
$this->assertTrue($user->isEmailTwoFactor());
|
||||
|
||||
$user->setEmailTwoFactor(false);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public function testUserEnable2faGoogle()
|
||||
{
|
||||
$this->logInAs('admin');
|
||||
$client = $this->getClient();
|
||||
|
||||
$crawler = $client->request('GET', '/config/otp/app');
|
||||
|
||||
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
// restore user
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em
|
||||
->getRepository('WallabagUserBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
|
||||
$this->assertTrue($user->isGoogleTwoFactor());
|
||||
$this->assertGreaterThan(0, $user->getBackupCodes());
|
||||
|
||||
$user->setGoogleAuthenticatorSecret(false);
|
||||
$user->setBackupCodes(null);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public function testUserEnable2faGoogleCancel()
|
||||
{
|
||||
$this->logInAs('admin');
|
||||
$client = $this->getClient();
|
||||
|
||||
$crawler = $client->request('GET', '/config/otp/app');
|
||||
|
||||
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
// restore user
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em
|
||||
->getRepository('WallabagUserBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
|
||||
$this->assertTrue($user->isGoogleTwoFactor());
|
||||
$this->assertGreaterThan(0, $user->getBackupCodes());
|
||||
|
||||
$crawler = $client->request('GET', '/config/otp/app/cancel');
|
||||
|
||||
$this->assertSame(302, $client->getResponse()->getStatusCode());
|
||||
|
||||
$user = $em
|
||||
->getRepository('WallabagUserBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
|
||||
$this->assertFalse($user->isGoogleTwoFactor());
|
||||
$this->assertEmpty($user->getBackupCodes());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class SecurityControllerTest extends WallabagCoreTestCase
|
|||
$this->assertContains('config.form_rss.description', $crawler->filter('body')->extract(['_text'])[0]);
|
||||
}
|
||||
|
||||
public function testLoginWith2Factor()
|
||||
public function testLoginWith2FactorEmail()
|
||||
{
|
||||
$client = $this->getClient();
|
||||
|
||||
|
@ -42,7 +42,7 @@ class SecurityControllerTest extends WallabagCoreTestCase
|
|||
$user = $em
|
||||
->getRepository('WallabagUserBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
$user->setTwoFactorAuthentication(true);
|
||||
$user->setEmailTwoFactor(true);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
|
||||
|
@ -54,12 +54,12 @@ class SecurityControllerTest extends WallabagCoreTestCase
|
|||
$user = $em
|
||||
->getRepository('WallabagUserBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
$user->setTwoFactorAuthentication(false);
|
||||
$user->setEmailTwoFactor(false);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public function testTrustedComputer()
|
||||
public function testLoginWith2FactorGoogle()
|
||||
{
|
||||
$client = $this->getClient();
|
||||
|
||||
|
@ -69,15 +69,27 @@ class SecurityControllerTest extends WallabagCoreTestCase
|
|||
return;
|
||||
}
|
||||
|
||||
$client->followRedirects();
|
||||
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
$user = $em
|
||||
->getRepository('WallabagUserBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
$user->setGoogleAuthenticatorSecret('26LDIHYGHNELOQEM');
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
|
||||
$date = new \DateTime();
|
||||
$user->addTrustedComputer('ABCDEF', $date->add(new \DateInterval('P1M')));
|
||||
$this->assertTrue($user->isTrustedComputer('ABCDEF'));
|
||||
$this->assertFalse($user->isTrustedComputer('FEDCBA'));
|
||||
$this->logInAsUsingHttp('admin');
|
||||
$crawler = $client->request('GET', '/config');
|
||||
$this->assertContains('scheb_two_factor.trusted', $crawler->filter('body')->extract(['_text'])[0]);
|
||||
|
||||
// restore user
|
||||
$user = $em
|
||||
->getRepository('WallabagUserBundle:User')
|
||||
->findOneByUsername('admin');
|
||||
$user->setGoogleAuthenticatorSecret(null);
|
||||
$em->persist($user);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public function testEnabledRegistration()
|
||||
|
|
|
@ -163,7 +163,7 @@ class ContentProxyTest extends TestCase
|
|||
|
||||
$this->assertSame('http://1.1.1.1', $entry->getUrl());
|
||||
$this->assertSame('this is my title', $entry->getTitle());
|
||||
$this->assertContains('this is my content', $entry->getContent());
|
||||
$this->assertContains('content', $entry->getContent());
|
||||
$this->assertSame('http://3.3.3.3/cover.jpg', $entry->getPreviewPicture());
|
||||
$this->assertSame('text/html', $entry->getMimetype());
|
||||
$this->assertSame('fr', $entry->getLanguage());
|
||||
|
@ -205,7 +205,7 @@ class ContentProxyTest extends TestCase
|
|||
|
||||
$this->assertSame('http://1.1.1.1', $entry->getUrl());
|
||||
$this->assertSame('this is my title', $entry->getTitle());
|
||||
$this->assertContains('this is my content', $entry->getContent());
|
||||
$this->assertContains('content', $entry->getContent());
|
||||
$this->assertNull($entry->getPreviewPicture());
|
||||
$this->assertSame('text/html', $entry->getMimetype());
|
||||
$this->assertSame('fr', $entry->getLanguage());
|
||||
|
@ -247,7 +247,7 @@ class ContentProxyTest extends TestCase
|
|||
|
||||
$this->assertSame('http://1.1.1.1', $entry->getUrl());
|
||||
$this->assertSame('this is my title', $entry->getTitle());
|
||||
$this->assertContains('this is my content', $entry->getContent());
|
||||
$this->assertContains('content', $entry->getContent());
|
||||
$this->assertSame('text/html', $entry->getMimetype());
|
||||
$this->assertNull($entry->getLanguage());
|
||||
$this->assertSame('200', $entry->getHttpStatus());
|
||||
|
@ -296,7 +296,7 @@ class ContentProxyTest extends TestCase
|
|||
|
||||
$this->assertSame('http://1.1.1.1', $entry->getUrl());
|
||||
$this->assertSame('this is my title', $entry->getTitle());
|
||||
$this->assertContains('this is my content', $entry->getContent());
|
||||
$this->assertContains('content', $entry->getContent());
|
||||
$this->assertNull($entry->getPreviewPicture());
|
||||
$this->assertSame('text/html', $entry->getMimetype());
|
||||
$this->assertSame('fr', $entry->getLanguage());
|
||||
|
@ -332,7 +332,7 @@ class ContentProxyTest extends TestCase
|
|||
|
||||
$this->assertSame('http://1.1.1.1', $entry->getUrl());
|
||||
$this->assertSame('this is my title', $entry->getTitle());
|
||||
$this->assertContains('this is my content', $entry->getContent());
|
||||
$this->assertContains('content', $entry->getContent());
|
||||
$this->assertSame('text/html', $entry->getMimetype());
|
||||
$this->assertSame('fr', $entry->getLanguage());
|
||||
$this->assertSame(4.0, $entry->getReadingTime());
|
||||
|
@ -371,7 +371,7 @@ class ContentProxyTest extends TestCase
|
|||
|
||||
$this->assertSame('http://1.1.1.1', $entry->getUrl());
|
||||
$this->assertSame('this is my title', $entry->getTitle());
|
||||
$this->assertContains('this is my content', $entry->getContent());
|
||||
$this->assertContains('content', $entry->getContent());
|
||||
$this->assertSame('text/html', $entry->getMimetype());
|
||||
$this->assertSame('fr', $entry->getLanguage());
|
||||
$this->assertSame(4.0, $entry->getReadingTime());
|
||||
|
@ -406,7 +406,7 @@ class ContentProxyTest extends TestCase
|
|||
|
||||
$this->assertSame('http://1.1.1.1', $entry->getUrl());
|
||||
$this->assertSame('this is my title', $entry->getTitle());
|
||||
$this->assertContains('this is my content', $entry->getContent());
|
||||
$this->assertContains('content', $entry->getContent());
|
||||
$this->assertSame('text/html', $entry->getMimetype());
|
||||
$this->assertSame('fr', $entry->getLanguage());
|
||||
$this->assertSame(4.0, $entry->getReadingTime());
|
||||
|
|
|
@ -33,7 +33,7 @@ TWIG;
|
|||
public function testSendEmail()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setTwoFactorAuthentication(true);
|
||||
$user->setEmailTwoFactor(true);
|
||||
$user->setEmailAuthCode(666666);
|
||||
$user->setEmail('test@wallabag.io');
|
||||
$user->setName('Bob');
|
||||
|
|
Loading…
Reference in a new issue