commit 37630d8e86401d994c025798bc007afe0af83470
parent a671c8ce1c9456061b69217c64342f06d40009db
Author: Felicitus <felicitus@felicitus.org>
Date: Wed, 9 Dec 2015 16:48:49 +0100
Added a new protected flag which allows an administrator to protect a user account from changes.
Diffstat:
6 files changed, 167 insertions(+), 9 deletions(-)
diff --git a/src/PartKeepr/AuthBundle/Command/ProtectUserCommand.php b/src/PartKeepr/AuthBundle/Command/ProtectUserCommand.php
@@ -0,0 +1,30 @@
+<?php
+namespace PartKeepr\AuthBundle\Command;
+
+use PartKeepr\AuthBundle\Services\UserService;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+
+class ProtectUserCommand extends ContainerAwareCommand
+{
+ public function configure()
+ {
+ parent::configure();
+ $this->setName('partkeepr:user:protect');
+ $this->setDescription("Protects a given user against changes");
+ $this->addArgument("username", InputArgument::REQUIRED, "The username to protect against changes");
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output)
+ {
+ $userService = $this->getContainer()->get("partkeepr.userservice");
+
+ $user = $userService->getProxyUser($input->getArgument("username"), $userService->getBuiltinProvider());
+ $userService->protect($user);
+ }
+}
+
+
diff --git a/src/PartKeepr/AuthBundle/Command/UnprotectUserCommand.php b/src/PartKeepr/AuthBundle/Command/UnprotectUserCommand.php
@@ -0,0 +1,30 @@
+<?php
+namespace PartKeepr\AuthBundle\Command;
+
+use PartKeepr\AuthBundle\Services\UserService;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+
+class UnprotectUserCommand extends ContainerAwareCommand
+{
+ public function configure()
+ {
+ parent::configure();
+ $this->setName('partkeepr:user:unprotect');
+ $this->setDescription("Unprotects a given user against changes");
+ $this->addArgument("username", InputArgument::REQUIRED, "The username to unprotect against changes");
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output)
+ {
+ $userService = $this->getContainer()->get("partkeepr.userservice");
+
+ $user = $userService->getProxyUser($input->getArgument("username"), $userService->getBuiltinProvider());
+ $userService->unprotect($user);
+ }
+}
+
+
diff --git a/src/PartKeepr/AuthBundle/Entity/User.php b/src/PartKeepr/AuthBundle/Entity/User.php
@@ -95,6 +95,15 @@ class User extends BaseEntity implements UserInterface, EquatableInterface
private $active;
/**
+ * Defines if the user is protected. Protection defines that the user may not be changed or removed.
+ * @ORM\Column(type="boolean")
+ * @Groups({"default"})
+ *
+ * @var bool
+ */
+ private $protected;
+
+ /**
* Creates a new user object.
*
* @param string $username The username to set (optional)
@@ -113,6 +122,8 @@ class User extends BaseEntity implements UserInterface, EquatableInterface
}
$this->setAdmin(false);
+ $this->setActive(true);
+ $this->setProtected(false);
}
/**
@@ -126,6 +137,22 @@ class User extends BaseEntity implements UserInterface, EquatableInterface
}
/**
+ * @return mixed
+ */
+ public function getProtected()
+ {
+ return $this->protected;
+ }
+
+ /**
+ * @param mixed $protected
+ */
+ public function setProtected($protected)
+ {
+ $this->protected = $protected;
+ }
+
+ /**
* Returns if the user is active
*
* @return boolean
@@ -261,6 +288,8 @@ class User extends BaseEntity implements UserInterface, EquatableInterface
/**
* Sets the new password. Used for password changes
+ *
+ * @param string $password The new password
*/
public function setNewPassword($password)
{
diff --git a/src/PartKeepr/AuthBundle/Services/UserService.php b/src/PartKeepr/AuthBundle/Services/UserService.php
@@ -1,7 +1,6 @@
<?php
namespace PartKeepr\AuthBundle\Services;
-
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\QueryBuilder;
@@ -9,7 +8,6 @@ use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\Util\UserManipulator;
use PartKeepr\AuthBundle\Entity\User;
use PartKeepr\AuthBundle\Entity\UserProvider;
-use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
class UserService
@@ -48,6 +46,11 @@ class UserService
$this->userManager = $userManager;
}
+ /**
+ * Returns the PartKeeprUser based on the user token within the Symfony2 environment.
+ *
+ * @return User The proxy user
+ */
public function getUser()
{
$tokenProvider = $this->tokenStorage->getToken()->getAttribute("provider");
@@ -55,7 +58,7 @@ class UserService
$provider = $this->getProvider($tokenProvider);
$username = $this->tokenStorage->getToken()->getUsername();
- return $this->getProxyUser($username, $provider);
+ return $this->getProxyUser($username, $provider, true);
}
public function getProvider($providerClass)
@@ -84,7 +87,9 @@ class UserService
/**
* Syncronizes the data of the given user with the FOSRestBundle
+ *
* @throws \Exception If the password was not set
+ *
* @param $user
*/
public function syncData(User $user)
@@ -139,7 +144,18 @@ class UserService
return $this->getProviderByType(self::BUILTIN_PROVIDER);
}
- public function getProxyUser($username, $provider)
+ /**
+ * Returns the proxy user for a given username and provider.
+ *
+ * @param $username
+ * @param $provider
+ * @param bool|false $create If set to true
+ *
+ * @return mixed|User
+ * @throws NoResultException
+ * @throws \Doctrine\ORM\NonUniqueResultException
+ */
+ public function getProxyUser($username, UserProvider $provider, $create = false)
{
/**
* @var QueryBuilder $queryBuilder
@@ -160,7 +176,11 @@ class UserService
return $user;
} catch (NoResultException $e) {
- return $this->createProxyUser($username, $provider);
+ if ($create === false) {
+ throw $e;
+ } else {
+ return $this->createProxyUser($username, $provider);
+ }
}
}
@@ -169,9 +189,31 @@ class UserService
{
$user = new User($username, $provider);
$user->setLegacy(false);
+ $user->setProtected(false);
+ $user->setActive(true);
$this->entityManager->persist($user);
$this->entityManager->flush();
return $user;
}
+
+ /**
+ * Protects a given user against changes.
+ * @param User $user
+ */
+ public function protect(User $user)
+ {
+ $user->setProtected(true);
+ $this->entityManager->flush();
+ }
+
+ /**
+ * Unprotects a given user against changes.
+ * @param User $user
+ */
+ public function unprotect(User $user)
+ {
+ $user->setProtected(false);
+ $this->entityManager->flush();
+ }
}
diff --git a/src/PartKeepr/AuthBundle/Tests/Services/UserPreferenceServiceTest.php b/src/PartKeepr/AuthBundle/Tests/Services/UserPreferenceServiceTest.php
@@ -14,7 +14,7 @@ class UserPreferenceServiceTest extends WebTestCase
/**
* @var User $user
*/
- $user = $userService->getProxyUser("admin", $userService->getBuiltinProvider());
+ $user = $userService->getProxyUser("admin", $userService->getBuiltinProvider(), true);
$service->setPreference($user, "foo", "bar");
$this->assertEquals("bar", $service->getPreferenceValue($user, "foo"));
@@ -55,7 +55,7 @@ class UserPreferenceServiceTest extends WebTestCase
* @var User $user
*/
$user = $this->getContainer()->get("partkeepr.userservice")->getProxyUser("admin",
- $userService->getBuiltinProvider());
+ $userService->getBuiltinProvider(), true);
$this->setExpectedException("PartKeepr\AuthBundle\Exceptions\UserPreferenceNotFoundException");
$service->getPreference($user, "BLA");
diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/User/UserEditor.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/User/UserEditor.js
@@ -35,14 +35,35 @@ Ext.define('PartKeepr.UserEditor', {
fieldLabel: i18n("Active"),
name: "active",
hidden: true
+ }, {
+ value: i18n("This is a protected user, which may not be changed"),
+ xtype: 'displayfield',
+ itemId: 'protectedNotice',
+ hidden: true
}
];
- this.on("startEdit", this.toggleLegacyField, this, {delay: 200});
+ this.on("startEdit", this.onStartEdit, this, {delay: 200});
this.callParent();
},
- toggleLegacyField: function ()
+ onStartEdit: function ()
{
+ if (this.record.get("protected") === true) {
+ this.items.each(function (item) {
+ if (item instanceof Ext.form.field.Base && !(item instanceof Ext.form.field.Display)) {
+ item.disable();
+ }
+ });
+ this.saveButton.disable();
+ } else {
+ this.items.each(function (item) {
+ if (item instanceof Ext.form.field.Base && !(item instanceof Ext.form.field.Display)) {
+ item.enable();
+ }
+ });
+ this.saveButton.enable();
+ }
+
var isBuiltInProvider = this.record.getProvider() !== null &&
this.record.getProvider().get("type") === "Builtin" &&
this.record.get("legacy") === false;
@@ -57,6 +78,12 @@ Ext.define('PartKeepr.UserEditor', {
this.down("#activeCheckbox").setValue(true);
}
+ if (this.record.get("protected") === true) {
+ this.down("#protectedNotice").setVisible(true);
+ } else {
+ this.down("#protectedNotice").setVisible(false);
+ }
+
if (this.record.get("legacy") === true) {
this.down("#legacyField").setVisible(true);
} else {