allow to disable user preferences by permission (#895)

This commit is contained in:
Kevin Papst
2019-07-01 19:37:20 +02:00
committed by GitHub
parent 94d68c8b64
commit 90980f40f5
10 changed files with 58 additions and 21 deletions

View File

@@ -22,4 +22,14 @@ class ThemeConfiguration implements SystemBundleConfiguration
{ {
return (string) $this->find('select_type'); return (string) $this->find('select_type');
} }
public function getTitle(): ?string
{
$title = $this->find('branding.title');
if (null === $title) {
return null;
}
return (string) $title;
}
} }

View File

@@ -335,6 +335,9 @@ class Configuration implements ConfigurationInterface
->scalarNode('company') ->scalarNode('company')
->defaultNull() ->defaultNull()
->end() ->end()
->scalarNode('title')
->defaultNull()
->end()
->end() ->end()
->end() ->end()
->end() ->end()

View File

@@ -64,12 +64,13 @@ class ThemeOptionsSubscriber implements EventSubscriberInterface
/** @var User $user */ /** @var User $user */
$user = $this->storage->getToken()->getUser(); $user = $this->storage->getToken()->getUser();
$skin = '';
foreach ($user->getPreferences() as $ref) { foreach ($user->getPreferences() as $ref) {
$name = $ref->getName(); $name = $ref->getName();
switch ($name) { switch ($name) {
case UserPreference::SKIN: case UserPreference::SKIN:
$skin = 'skin-' . $ref->getValue(); if (!empty($ref->getValue())) {
$this->helper->setOption('skin', 'skin-' . $ref->getValue());
}
break; break;
case 'theme.collapsed_sidebar': case 'theme.collapsed_sidebar':
@@ -77,12 +78,6 @@ class ThemeOptionsSubscriber implements EventSubscriberInterface
break; break;
} }
} }
if (empty($skin)) {
$skin = 'skin-green';
}
$this->helper->setOption('skin', $skin);
} }
/** /**

View File

@@ -97,7 +97,6 @@ class UserPreferenceSubscriber implements EventSubscriberInterface
(new UserPreference()) (new UserPreference())
->setName(UserPreference::SKIN) ->setName(UserPreference::SKIN)
->setValue('green')
->setType(SkinType::class), ->setType(SkinType::class),
(new UserPreference()) (new UserPreference())

View File

@@ -9,6 +9,7 @@
namespace App\Twig; namespace App\Twig;
use App\Configuration\ThemeConfiguration;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Extension\AbstractExtension; use Twig\Extension\AbstractExtension;
use Twig\TwigFunction; use Twig\TwigFunction;
@@ -19,13 +20,18 @@ class TitleExtension extends AbstractExtension
* @var TranslatorInterface * @var TranslatorInterface
*/ */
protected $translator; protected $translator;
/**
* @var ThemeConfiguration
*/
protected $configuration;
/** /**
* @param TranslatorInterface $translator * @param TranslatorInterface $translator
*/ */
public function __construct(TranslatorInterface $translator) public function __construct(TranslatorInterface $translator, ThemeConfiguration $configuration)
{ {
$this->translator = $translator; $this->translator = $translator;
$this->configuration = $configuration;
} }
/** /**
@@ -38,13 +44,10 @@ class TitleExtension extends AbstractExtension
]; ];
} }
/** public function generateTitle(?string $prefix = null, string $delimiter = ' '): string
* @param null|string $prefix
* @param string $delimiter
* @return string
*/
public function generateTitle(?string $prefix = null, string $delimiter = ' ')
{ {
return ($prefix ?? '') . 'Kimai' . $delimiter . $this->translator->trans('time_tracking', [], 'messages'); $title = $this->configuration->getTitle() ?? 'Kimai';
return ($prefix ?? '') . ($title) . $delimiter . $this->translator->trans('time_tracking', [], 'messages');
} }
} }

View File

@@ -83,13 +83,13 @@ class UserVoter extends AbstractVoter
// used in templates and ProfileController // used in templates and ProfileController
case self::VIEW: case self::VIEW:
case self::EDIT: case self::EDIT:
case self::PREFERENCES:
// always allow the user to edit these own settings // always allow the user to edit these own settings
if ($subject->getId() === $user->getId()) { if ($subject->getId() === $user->getId()) {
return true; return true;
} }
// no break on purpose // no break on purpose
case self::PREFERENCES:
case self::PASSWORD: case self::PASSWORD:
case self::API_TOKEN: case self::API_TOKEN:
case self::ROLES: case self::ROLES:

View File

@@ -121,6 +121,7 @@
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{% if app.user is not null %} {% if app.user is not null %}
{% if is_granted('view', app.user) %}
<li> <li>
<a href="{{ path('user_profile', {'username' : app.user.username}) }}"> <a href="{{ path('user_profile', {'username' : app.user.username}) }}">
<h4 class="control-sidebar-subheading"> <h4 class="control-sidebar-subheading">
@@ -129,6 +130,8 @@
</h4> </h4>
</a> </a>
</li> </li>
{% endif %}
{% if is_granted('edit', app.user) %}
<li> <li>
<a href="{{ path('user_profile_edit', {'username' : app.user.username}) }}"> <a href="{{ path('user_profile_edit', {'username' : app.user.username}) }}">
<h4 class="control-sidebar-subheading"> <h4 class="control-sidebar-subheading">
@@ -137,6 +140,8 @@
</h4> </h4>
</a> </a>
</li> </li>
{% endif %}
{% if is_granted('preferences', app.user) %}
<li> <li>
<a href="{{ path('user_profile_preferences', {'username' : app.user.username}) }}"> <a href="{{ path('user_profile_preferences', {'username' : app.user.username}) }}">
<h4 class="control-sidebar-subheading"> <h4 class="control-sidebar-subheading">
@@ -145,6 +150,7 @@
</h4> </h4>
</a> </a>
</li> </li>
{% endif %}
<li> <li>
<a href="{{ path('fos_user_security_logout') }}"> <a href="{{ path('fos_user_security_logout') }}">
<h4 class="control-sidebar-subheading"> <h4 class="control-sidebar-subheading">

View File

@@ -340,7 +340,7 @@ class ProfileControllerTest extends ControllerBaseTest
$user = $this->getUserByName($em, $username); $user = $this->getUserByName($em, $username);
$this->assertEquals($hourlyRateOriginal, $user->getPreferenceValue(UserPreference::HOURLY_RATE)); $this->assertEquals($hourlyRateOriginal, $user->getPreferenceValue(UserPreference::HOURLY_RATE));
$this->assertEquals('green', $user->getPreferenceValue(UserPreference::SKIN)); $this->assertNull($user->getPreferenceValue(UserPreference::SKIN));
$this->assertEquals(false, $user->getPreferenceValue('theme.collapsed_sidebar')); $this->assertEquals(false, $user->getPreferenceValue('theme.collapsed_sidebar'));
$this->assertEquals('month', $user->getPreferenceValue('calendar.initial_view')); $this->assertEquals('month', $user->getPreferenceValue('calendar.initial_view'));

View File

@@ -107,6 +107,7 @@ class AppExtensionTest extends TestCase
'logo' => null, 'logo' => null,
'mini' => null, 'mini' => null,
'company' => null, 'company' => null,
'title' => null,
], ],
], ],
'kimai.theme.select_type' => null, 'kimai.theme.select_type' => null,

View File

@@ -9,6 +9,9 @@
namespace App\Tests\Twig; namespace App\Tests\Twig;
use App\Configuration\ThemeConfiguration;
use App\Entity\Configuration;
use App\Tests\Configuration\TestConfigLoader;
use App\Twig\TitleExtension; use App\Twig\TitleExtension;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
@@ -19,12 +22,20 @@ use Twig\TwigFunction;
*/ */
class TitleExtensionTest extends TestCase class TitleExtensionTest extends TestCase
{ {
protected function getSut(): TitleExtension protected function getSut(string $title = null): TitleExtension
{ {
$translator = $this->getMockBuilder(TranslatorInterface::class)->getMock(); $translator = $this->getMockBuilder(TranslatorInterface::class)->getMock();
$translator->method('trans')->willReturn('foo'); $translator->method('trans')->willReturn('foo');
return new TitleExtension($translator); $configs = [
(new Configuration())->setName('theme.branding.title')->setValue($title)
];
$loader = new TestConfigLoader($configs);
$configuration = new ThemeConfiguration($loader, ['branding' => ['title' => null]]);
return new TitleExtension($translator, $configuration);
} }
public function testGetFunctions() public function testGetFunctions()
@@ -49,4 +60,13 @@ class TitleExtensionTest extends TestCase
$this->assertEquals('<b>Kimai</b> ... foo', $sut->generateTitle('<b>', '</b> ... ')); $this->assertEquals('<b>Kimai</b> ... foo', $sut->generateTitle('<b>', '</b> ... '));
$this->assertEquals('Kimai | foo', $sut->generateTitle(null, ' | ')); $this->assertEquals('Kimai | foo', $sut->generateTitle(null, ' | '));
} }
public function testGetBrandedTitle()
{
$sut = $this->getSut('MyCompany');
$this->assertEquals('MyCompany foo', $sut->generateTitle());
$this->assertEquals('sdfsdf | MyCompany foo', $sut->generateTitle('sdfsdf | '));
$this->assertEquals('<b>MyCompany</b> ... foo', $sut->generateTitle('<b>', '</b> ... '));
$this->assertEquals('MyCompany | foo', $sut->generateTitle(null, ' | '));
}
} }