Add menu access to site credentials CRUD

This commit is contained in:
Jeremy Benoist 2017-05-01 22:13:35 +02:00
parent 5a9bc00726
commit b8427f22f0
No known key found for this signature in database
GPG key ID: BCA73962457ACC3C
22 changed files with 258 additions and 14 deletions

View file

@ -0,0 +1,34 @@
<?php
namespace Wallabag\CoreBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Wallabag\CoreBundle\Entity\SiteCredential;
class LoadSiteCredentialData extends AbstractFixture implements OrderedFixtureInterface
{
/**
* {@inheritdoc}
*/
public function load(ObjectManager $manager)
{
$credential = new SiteCredential($this->getReference('admin-user'));
$credential->setHost('example.com');
$credential->setUsername('foo');
$credential->setPassword('bar');
$manager->persist($credential);
$manager->flush();
}
/**
* {@inheritdoc}
*/
public function getOrder()
{
return 50;
}
}

View file

@ -7,7 +7,7 @@ use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfigBuilder;
use Graby\SiteConfig\ConfigBuilder;
use Psr\Log\LoggerInterface;
use Wallabag\CoreBundle\Repository\SiteCredentialRepository;
use Wallabag\UserBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
class GrabySiteConfigBuilder implements SiteConfigBuilder
{
@ -27,7 +27,7 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder
private $logger;
/**
* @var User
* @var Wallabag\UserBundle\Entity\User|null
*/
private $currentUser;
@ -36,16 +36,19 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder
* GrabySiteConfigBuilder constructor.
*
* @param ConfigBuilder $grabyConfigBuilder
* @param User $currentUser
* @param TokenStorage $token
* @param SiteCredentialRepository $credentialRepository
* @param LoggerInterface $logger
*/
public function __construct(ConfigBuilder $grabyConfigBuilder, User $currentUser, SiteCredentialRepository $credentialRepository, LoggerInterface $logger)
public function __construct(ConfigBuilder $grabyConfigBuilder, TokenStorage $token, SiteCredentialRepository $credentialRepository, LoggerInterface $logger)
{
$this->grabyConfigBuilder = $grabyConfigBuilder;
$this->credentialRepository = $credentialRepository;
$this->currentUser = $currentUser;
$this->logger = $logger;
if ($token->getToken()) {
$this->currentUser = $token->getToken()->getUser();
}
}
/**
@ -59,7 +62,10 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder
$host = substr($host, 4);
}
$credentials = $this->credentialRepository->findOneByHostAndUser($host, $this->currentUser->getId());
$credentials = null;
if ($this->currentUser) {
$credentials = $this->credentialRepository->findOneByHostAndUser($host, $this->currentUser->getId());
}
if (null === $credentials) {
$this->logger->debug('Auth: no credentials available for host.', ['host' => $host]);

View file

@ -63,7 +63,7 @@ services:
class: Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder
arguments:
- "@wallabag_core.graby.config_builder"
- "@=service('security.token_storage').getToken().getUser()"
- "@security.token_storage"
- "@wallabag_core.site_credential_repository"
- '@logger'
tags:

View file

@ -32,6 +32,7 @@ menu:
# save_link: 'Save a link'
back_to_unread: 'Tilbage til de ulæste artikler'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Tilføj ny artikel'
search: 'Søg'

View file

@ -32,6 +32,7 @@ menu:
save_link: 'Link speichern'
back_to_unread: 'Zurück zu ungelesenen Artikeln'
users_management: 'Benutzerverwaltung'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Neuen Artikel hinzufügen'
search: 'Suche'

View file

@ -32,6 +32,7 @@ menu:
save_link: 'Save a link'
back_to_unread: 'Back to unread articles'
users_management: 'Users management'
site_credentials: 'Site credentials'
top:
add_new_entry: 'Add a new entry'
search: 'Search'

View file

@ -32,6 +32,7 @@ menu:
save_link: 'Guardar un enlace'
back_to_unread: 'Volver a los artículos sin leer'
users_management: 'Configuración de usuarios'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Añadir un nuevo artículo'
search: 'Buscar'

View file

@ -32,6 +32,7 @@ menu:
save_link: 'ذخیرهٔ یک پیوند'
back_to_unread: 'بازگشت به خوانده‌نشده‌ها'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'افزودن مقالهٔ تازه'
search: 'جستجو'

View file

@ -32,6 +32,7 @@ menu:
save_link: "Sauvegarder un nouvel article"
back_to_unread: "Retour aux articles non lus"
users_management: "Gestion des utilisateurs"
site_credentials: 'Accès aux sites'
top:
add_new_entry: "Sauvegarder un nouvel article"
search: "Rechercher"

View file

@ -32,6 +32,7 @@ menu:
save_link: 'Salva collegamento'
back_to_unread: 'Torna ai contenuti non letti'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Aggiungi un nuovo contenuto'
search: 'Cerca'

View file

@ -32,6 +32,7 @@ menu:
save_link: 'Enregistrar un novèl article'
back_to_unread: 'Tornar als articles pas legits'
users_management: 'Gestion dels utilizaires'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Enregistrar un novèl article'
search: 'Cercar'

View file

@ -32,6 +32,7 @@ menu:
save_link: 'Zapisz link'
back_to_unread: 'Powrót do nieprzeczytanych artykułów'
users_management: 'Zarządzanie użytkownikami'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Dodaj nowy wpis'
search: 'Szukaj'

View file

@ -32,6 +32,7 @@ menu:
save_link: 'Salvar um link'
back_to_unread: 'Voltar para os artigos não lidos'
users_management: 'Gestão de Usuários'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Adicionar uma nova entrada'
search: 'Pesquisa'

View file

@ -32,6 +32,7 @@ menu:
# save_link: 'Save a link'
back_to_unread: 'Înapoi la articolele necitite'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Introdu un nou articol'
search: 'Căutare'

View file

@ -32,6 +32,7 @@ menu:
# save_link: 'Save a link'
back_to_unread: 'Okunmayan makalelere geri dön'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
top:
add_new_entry: 'Yeni bir makale ekle'
search: 'Ara'

View file

@ -49,7 +49,7 @@
<button onclick="return confirm('{{ 'site_credential.form.delete_confirm'|trans|escape('js') }}')" type="submit" class="btn waves-effect waves-light red">{{ 'site_credential.form.delete'|trans }}</button>
{{ form_end(delete_form) }}
</p>
<p><a class="waves-effect waves-light btn blue-grey" href="{{ path('site_credential_index') }}">{{ 'site_credential.form.back_to_list'|trans }}</a></p>
<p><a class="waves-effect waves-light btn blue-grey" href="{{ path('site_credentials_index') }}">{{ 'site_credential.form.back_to_list'|trans }}</a></p>
</div>
</div>
</div>

View file

@ -25,7 +25,7 @@
<td>{{ credential.host }}</td>
<td>{{ credential.username }}</td>
<td>
<a href="{{ path('site_credential_edit', { 'id': credential.id }) }}">{{ 'site_credential.list.edit_action'|trans }}</a>
<a href="{{ path('site_credentials_edit', { 'id': credential.id }) }}">{{ 'site_credential.list.edit_action'|trans }}</a>
</td>
</tr>
{% endfor %}
@ -33,7 +33,7 @@
</table>
<br />
<p>
<a href="{{ path('site_credential_new') }}" class="waves-effect waves-light btn">{{ 'site_credential.list.create_new_one'|trans }}</a>
<a href="{{ path('site_credentials_new') }}" class="waves-effect waves-light btn">{{ 'site_credential.list.create_new_one'|trans }}</a>
</p>
</div>
</div>

View file

@ -42,7 +42,7 @@
{{ form_widget(form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
{{ form_rest(form) }}
</form>
<p><a class="waves-effect waves-light btn blue-grey" href="{{ path('site_credential_index') }}">{{ 'site_credential.form.back_to_list'|trans }}</a></p>
<p><a class="waves-effect waves-light btn blue-grey" href="{{ path('site_credentials_index') }}">{{ 'site_credential.form.back_to_list'|trans }}</a></p>
</div>
</div>
</div>

View file

@ -38,6 +38,9 @@
{{ render(controller("WallabagCoreBundle:Entry:searchForm", {'currentRoute': app.request.attributes.get('_route')})) }}
</div>
</li>
{% if craue_setting('restricted_access') %}
<li class="menu site_credentials"><a href="{{ path('site_credentials_index') }}">{{ 'menu.left.site_credentials'|trans }}</a></li>
{% endif %}
<li class="menu config"><a href="{{ path('config') }}">{{ 'menu.left.config'|trans }}</a></li>
{% if is_granted('ROLE_SUPER_ADMIN') %}
<li class="menu users"><a href="{{ path('user_index') }}">{{ 'menu.left.users_management'|trans }}</a></li>

View file

@ -66,6 +66,11 @@
<li class="bold {% if currentRoute == 'config' %}active{% endif %}">
<a class="waves-effect" href="{{ path('config') }}">{{ 'menu.left.config'|trans }}</a>
</li>
{% if craue_setting('restricted_access') %}
<li class="bold {% if currentRoute starts with 'site_credentials_' %}active{% endif %}">
<a class="waves-effect" href="{{ path('site_credentials_index') }}">{{ 'menu.left.site_credentials'|trans }}</a>
</li>
{% endif %}
{% if is_granted('ROLE_SUPER_ADMIN') %}
<li class="bold {% if currentRoute starts with 'user_' %}active{% endif %}">
<a class="waves-effect" href="{{ path('user_index') }}">{{ 'menu.left.users_management'|trans }}</a>

View file

@ -0,0 +1,140 @@
<?php
namespace Tests\Wallabag\CoreBundle\Controller;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
class SiteCredentialControllerTest extends WallabagCoreTestCase
{
public function testListSiteCredential()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/site-credentials/');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$body = $crawler->filter('body')->extract(['_text'])[0];
$this->assertContains('site_credential.description', $body);
$this->assertContains('site_credential.list.create_new_one', $body);
}
public function testNewSiteCredential()
{
$this->logInAs('admin');
$client = $this->getClient();
$crawler = $client->request('GET', '/site-credentials/new');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$body = $crawler->filter('body')->extract(['_text'])[0];
$this->assertContains('site_credential.new_site_credential', $body);
$this->assertContains('site_credential.form.back_to_list', $body);
$form = $crawler->filter('button[id=site_credential_save]')->form();
$data = [
'site_credential[host]' => 'google.io',
'site_credential[username]' => 'sergei',
'site_credential[password]' => 'microsoft',
];
$client->submit($form, $data);
$this->assertEquals(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertContains('flashes.site_credential.notice.added', $crawler->filter('body')->extract(['_text'])[0]);
}
/**
* @depends testNewSiteCredential
*/
public function testEditSiteCredential()
{
$this->logInAs('admin');
$client = $this->getClient();
$credential = $client->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('WallabagCoreBundle:SiteCredential')
->findOneByHost('google.io');
$crawler = $client->request('GET', '/site-credentials/'.$credential->getId().'/edit');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$body = $crawler->filter('body')->extract(['_text'])[0];
$this->assertContains('site_credential.edit_site_credential', $body);
$this->assertContains('site_credential.form.back_to_list', $body);
$form = $crawler->filter('button[id=site_credential_save]')->form();
$data = [
'site_credential[host]' => 'google.io',
'site_credential[username]' => 'larry',
'site_credential[password]' => 'microsoft',
];
$client->submit($form, $data);
$this->assertEquals(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertContains('flashes.site_credential.notice.updated', $crawler->filter('body')->extract(['_text'])[0]);
$this->assertContains('larry', $crawler->filter('input[id=site_credential_username]')->attr('value'));
}
/**
* @depends testNewSiteCredential
*/
public function testEditFromADifferentUserSiteCredential()
{
$this->logInAs('bob');
$client = $this->getClient();
$credential = $client->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('WallabagCoreBundle:SiteCredential')
->findOneByHost('google.io');
$client->request('GET', '/site-credentials/'.$credential->getId().'/edit');
$this->assertEquals(403, $client->getResponse()->getStatusCode());
}
/**
* @depends testNewSiteCredential
*/
public function testDeleteSiteCredential()
{
$this->logInAs('admin');
$client = $this->getClient();
$credential = $client->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('WallabagCoreBundle:SiteCredential')
->findOneByHost('google.io');
$crawler = $client->request('GET', '/site-credentials/'.$credential->getId().'/edit');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$deleteForm = $crawler->filter('body')->selectButton('site_credential.form.delete')->form();
$client->submit($deleteForm, []);
$this->assertEquals(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertContains('flashes.site_credential.notice.deleted', $crawler->filter('body')->extract(['_text'])[0]);
}
}

View file

@ -8,6 +8,8 @@ use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig;
use Graby\SiteConfig\SiteConfig as GrabySiteConfig;
use PHPUnit_Framework_TestCase;
use Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase
{
@ -17,7 +19,7 @@ class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase
public function testBuildConfigExists()
{
/* @var \Graby\SiteConfig\ConfigBuilder|\PHPUnit_Framework_MockObject_MockObject */
$grabyConfigBuilderMock = $this->getMockBuilder('\Graby\SiteConfig\ConfigBuilder')
$grabyConfigBuilderMock = $this->getMockBuilder('Graby\SiteConfig\ConfigBuilder')
->disableOriginalConstructor()
->getMock();
@ -38,9 +40,30 @@ class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase
$handler = new TestHandler();
$logger->pushHandler($handler);
$siteCrentialRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\SiteCredentialRepository')
->disableOriginalConstructor()
->getMock();
$siteCrentialRepo->expects($this->once())
->method('findOneByHostAndUser')
->with('example.com', 1)
->willReturn(['username' => 'foo', 'password' => 'bar']);
$user = $this->getMockBuilder('Wallabag\UserBundle\Entity\User')
->disableOriginalConstructor()
->getMock();
$user->expects($this->once())
->method('getId')
->willReturn(1);
$token = new UsernamePasswordToken($user, 'pass', 'provider');
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
$this->builder = new GrabySiteConfigBuilder(
$grabyConfigBuilderMock,
['example.com' => ['username' => 'foo', 'password' => 'bar']],
$tokenStorage,
$siteCrentialRepo,
$logger
);
@ -82,9 +105,30 @@ class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase
$handler = new TestHandler();
$logger->pushHandler($handler);
$siteCrentialRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\SiteCredentialRepository')
->disableOriginalConstructor()
->getMock();
$siteCrentialRepo->expects($this->once())
->method('findOneByHostAndUser')
->with('unknown.com', 1)
->willReturn(null);
$user = $this->getMockBuilder('Wallabag\UserBundle\Entity\User')
->disableOriginalConstructor()
->getMock();
$user->expects($this->once())
->method('getId')
->willReturn(1);
$token = new UsernamePasswordToken($user, 'pass', 'provider');
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
$this->builder = new GrabySiteConfigBuilder(
$grabyConfigBuilderMock,
[],
$tokenStorage,
$siteCrentialRepo,
$logger
);