added "create user" functionality (#37)

* added "create user" functionality #5
* improved user admin views
* added Role constraint and validator
This commit is contained in:
Kevin Papst
2018-01-06 18:33:01 +01:00
committed by GitHub
parent 3270ce7560
commit 56c994c46b
9 changed files with 245 additions and 39 deletions

View File

@@ -11,13 +11,15 @@
namespace AppBundle\Controller\Admin;
use AppBundle\Controller\AbstractController;
use AppBundle\Entity\User;
use AppBundle\Form\UserCreateType;
use Pagerfanta\Pagerfanta;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Symfony\Component\HttpFoundation\Request;
/**
* Controller used to manage users in the admin part of the site.
@@ -27,7 +29,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class UserController extends Controller
class UserController extends AbstractController
{
/**
* @Route("/", defaults={"page": 1}, name="admin_user")
@@ -42,4 +44,58 @@ class UserController extends Controller
return $this->render('admin/user.html.twig', ['entries' => $entries]);
}
/**
* @Route("/create", name="admin_user_create")
* @Method({"GET", "POST"})
*/
public function createAction(Request $request)
{
$user = new User();
$editForm = $this->createEditForm($user);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$password = $this->get('security.password_encoder')
->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
$user->setRoles([User::DEFAULT_ROLE]);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$this->flashSuccess('action.updated_successfully');
return $this->redirectToRoute(
'user_profile_edit', ['username' => $user->getUsername()]
);
}
return $this->render(
'admin/user_edit.html.twig',
[
'user' => $user,
'form' => $editForm->createView()
]
);
}
/**
* @param User $user
* @return \Symfony\Component\Form\FormInterface
*/
private function createEditForm(User $user)
{
return $this->createForm(
UserCreateType::class,
$user,
[
'action' => $this->generateUrl('admin_user_create'),
'method' => 'POST'
]
);
}
}

View File

@@ -2,19 +2,28 @@
namespace AppBundle\Entity;
use AppBundle\Validator\Constraints as KimaiAssert;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* User
*
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @ORM\Table(name="users", uniqueConstraints={@ORM\UniqueConstraint(name="name", columns={"name"})})
* @ORM\Table(name="users", uniqueConstraints={@ORM\UniqueConstraint(name="name", columns={"name"}), @ORM\UniqueConstraint(name="mail", columns={"mail"})})
* @UniqueEntity("username")
* @UniqueEntity("email")
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class User implements UserInterface
{
const DEFAULT_ROLE = 'ROLE_USER';
const DEFAULT_LANGUAGE = 'de';
/**
* @var int
*
@@ -27,7 +36,7 @@ class User implements UserInterface
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=160, nullable=false, unique=true)
* @ORM\Column(name="name", type="string", length=60, nullable=false, unique=true)
* @Assert\NotBlank()
* @Assert\Length(min=6, max=160)
*/
@@ -60,7 +69,8 @@ class User implements UserInterface
/**
* @var string
*
* @ORM\Column(name="alias", type="string", length=160, nullable=true)
* @ORM\Column(name="alias", type="string", length=60, nullable=true)
* @Assert\Length(max=160)
*/
private $alias;
@@ -68,13 +78,15 @@ class User implements UserInterface
* @var string
*
* @ORM\Column(name="language", type="string", length=5, nullable=true)
* @Assert\Language()
*/
private $language = 'de';
private $language = self::DEFAULT_LANGUAGE;
/**
* @var boolean
*
* @ORM\Column(name="active", type="boolean", nullable=false)
* @Assert\NotNull()
*/
private $active = true;
@@ -103,6 +115,7 @@ class User implements UserInterface
* @var string[]
*
* @ORM\Column(type="json_array")
* @KimaiAssert\Role()
*/
private $roles = [];
@@ -166,7 +179,7 @@ class User implements UserInterface
*/
public function setActive($active)
{
$this->active = $active;
$this->active = (bool) $active;
return $this;
}
@@ -305,10 +318,12 @@ class User implements UserInterface
/**
* @param string $language
* @return $this
*/
public function setLanguage($language)
{
$this->language = $language;
return $this;
}
/**

View File

@@ -0,0 +1,56 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Form;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Defines the form used to create Users.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class UserCreateType extends UserEditType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username', null, [
'label' => 'label.username',
'required' => true
])
->add('plainPassword', RepeatedType::class, [
'required' => true,
'type' => PasswordType::class,
'first_options' => array('label' => 'security.label.password'),
'second_options' => array('label' => 'security.label.password_repeat'),
]);
parent::buildForm($builder, $options);
}
/**
* {@inheritdoc}
*/
public function __configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => 'AppBundle:User',
]);
}
}

View File

@@ -0,0 +1,31 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class Role extends Constraint
{
const ROLE_ERROR = 'xd5hffg-dsfef3-426a-83d7-1f2d33hs5d84';
protected static $errorNames = array(
self::ROLE_ERROR => 'ROLE_ERROR',
);
public $message = 'This value is not a valid role.';
}

View File

@@ -0,0 +1,50 @@
<?php
/*
* This file is part of the Kimai package.
*
* (c) Kevin Papst <kevin@kevinpapst.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class RoleValidator extends ConstraintValidator
{
protected $allowedRoles = ['ROLE_CUSTOMER', 'ROLE_USER', 'ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_SUPER_ADMIN'];
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof Role) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Role');
}
$roles = $value;
if (!is_array($roles)) {
$roles = [$roles];
}
foreach($roles as $role) {
if (!is_string($role) || !in_array($role, $this->allowedRoles)) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($role))
->setCode(Role::ROLE_ERROR)
->addViolation();
}
}
}
}