fetch user preferences via API (#2905)
This commit is contained in:
@@ -32,6 +32,7 @@ nelmio_api_doc:
|
|||||||
- { alias: UserCreateForm, type: App\Form\API\UserApiCreateForm, groups: [Default, Entity, User, User_Entity] }
|
- { alias: UserCreateForm, type: App\Form\API\UserApiCreateForm, groups: [Default, Entity, User, User_Entity] }
|
||||||
- { alias: UserEditForm, type: App\Form\API\UserApiEditForm, groups: [Default, Entity, User, User_Entity] }
|
- { alias: UserEditForm, type: App\Form\API\UserApiEditForm, groups: [Default, Entity, User, User_Entity] }
|
||||||
- { alias: User, type: App\Entity\User, groups: [Default] }
|
- { alias: User, type: App\Entity\User, groups: [Default] }
|
||||||
|
- { alias: UserPreference, type: App\Entity\UserPreference, groups: [Default, User_Entity] }
|
||||||
- { alias: UserEntity, type: App\Entity\User, groups: [Default, Entity, User, User_Entity] }
|
- { alias: UserEntity, type: App\Entity\User, groups: [Default, Entity, User, User_Entity] }
|
||||||
- { alias: UserCollection, type: App\Entity\User, groups: [Default, Collection, User] }
|
- { alias: UserCollection, type: App\Entity\User, groups: [Default, Collection, User] }
|
||||||
- { alias: TeamEditForm, type: App\Form\API\TeamApiEditForm, groups: [Default, Entity, Team, Team_Entity] }
|
- { alias: TeamEditForm, type: App\Form\API\TeamApiEditForm, groups: [Default, Entity, Team, Team_Entity] }
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace App\API;
|
|||||||
|
|
||||||
use App\Configuration\SystemConfiguration;
|
use App\Configuration\SystemConfiguration;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
|
use App\Event\PrepareUserEvent;
|
||||||
use App\Form\API\UserApiCreateForm;
|
use App\Form\API\UserApiCreateForm;
|
||||||
use App\Form\API\UserApiEditForm;
|
use App\Form\API\UserApiEditForm;
|
||||||
use App\Repository\Query\UserQuery;
|
use App\Repository\Query\UserQuery;
|
||||||
@@ -26,6 +27,7 @@ use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
|
|||||||
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
|
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||||
use Swagger\Annotations as SWG;
|
use Swagger\Annotations as SWG;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
@@ -137,7 +139,7 @@ final class UserController extends BaseApiController
|
|||||||
* @ApiSecurity(name="apiUser")
|
* @ApiSecurity(name="apiUser")
|
||||||
* @ApiSecurity(name="apiToken")
|
* @ApiSecurity(name="apiToken")
|
||||||
*/
|
*/
|
||||||
public function getAction(int $id): Response
|
public function getAction(int $id, EventDispatcherInterface $dispatcher): Response
|
||||||
{
|
{
|
||||||
$user = $this->repository->find($id);
|
$user = $this->repository->find($id);
|
||||||
|
|
||||||
@@ -149,6 +151,10 @@ final class UserController extends BaseApiController
|
|||||||
throw new AccessDeniedHttpException('You are not allowed to view this profile');
|
throw new AccessDeniedHttpException('You are not allowed to view this profile');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we need to prepare the user preferences, which is done via an EventSubscriber
|
||||||
|
$event = new PrepareUserEvent($user);
|
||||||
|
$dispatcher->dispatch($event);
|
||||||
|
|
||||||
$view = new View($user, 200);
|
$view = new View($user, 200);
|
||||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||||
|
|
||||||
|
|||||||
@@ -373,6 +373,45 @@ class User implements UserInterface, EquatableInterface, \Serializable
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read-only list of of all visible user preferences.
|
||||||
|
*
|
||||||
|
* @Serializer\VirtualProperty
|
||||||
|
* @Serializer\SerializedName("preferences"),
|
||||||
|
* @Serializer\Groups({"User_Entity"})
|
||||||
|
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/UserPreference"))
|
||||||
|
*
|
||||||
|
* @internal only for API usage
|
||||||
|
* @return UserPreference[]
|
||||||
|
*/
|
||||||
|
public function getVisiblePreferences(): array
|
||||||
|
{
|
||||||
|
// hide all internal preferences, which are either available in other fields
|
||||||
|
// or which are only used within the Kimai UI
|
||||||
|
$skip = [
|
||||||
|
UserPreference::TIMEZONE,
|
||||||
|
UserPreference::LOCALE,
|
||||||
|
UserPreference::SKIN,
|
||||||
|
'calendar.initial_view',
|
||||||
|
'login.initial_view',
|
||||||
|
'reporting.initial_view',
|
||||||
|
'theme.collapsed_sidebar',
|
||||||
|
'theme.layout',
|
||||||
|
'theme.update_browser_title',
|
||||||
|
'timesheet.daily_stats',
|
||||||
|
'timesheet.export_decimal',
|
||||||
|
];
|
||||||
|
|
||||||
|
$all = [];
|
||||||
|
foreach ($this->preferences as $preference) {
|
||||||
|
if ($preference->isEnabled() && !\in_array($preference->getName(), $skip)) {
|
||||||
|
$all[] = $preference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $all;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection<UserPreference>
|
* @return Collection<UserPreference>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace App\Entity;
|
|||||||
|
|
||||||
use App\Form\Type\YesNoType;
|
use App\Form\Type\YesNoType;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use JMS\Serializer\Annotation as Serializer;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
@@ -23,6 +24,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||||||
* @ORM\UniqueConstraint(columns={"user_id", "name"})
|
* @ORM\UniqueConstraint(columns={"user_id", "name"})
|
||||||
* }
|
* }
|
||||||
* )
|
* )
|
||||||
|
*
|
||||||
|
* @Serializer\ExclusionPolicy("all")
|
||||||
*/
|
*/
|
||||||
class UserPreference
|
class UserPreference
|
||||||
{
|
{
|
||||||
@@ -53,6 +56,9 @@ class UserPreference
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
|
* @Serializer\Expose()
|
||||||
|
* @Serializer\Groups({"Default"})
|
||||||
|
*
|
||||||
* @ORM\Column(name="name", type="string", length=50, nullable=false)
|
* @ORM\Column(name="name", type="string", length=50, nullable=false)
|
||||||
* @Assert\NotNull()
|
* @Assert\NotNull()
|
||||||
* @Assert\Length(min=2, max=50, allowEmptyString=false)
|
* @Assert\Length(min=2, max=50, allowEmptyString=false)
|
||||||
@@ -61,6 +67,9 @@ class UserPreference
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
|
* @Serializer\Expose()
|
||||||
|
* @Serializer\Groups({"Default"})
|
||||||
|
*
|
||||||
* @ORM\Column(name="value", type="string", length=255, nullable=true)
|
* @ORM\Column(name="value", type="string", length=255, nullable=true)
|
||||||
*/
|
*/
|
||||||
private $value;
|
private $value;
|
||||||
|
|||||||
@@ -283,6 +283,12 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
|
|||||||
];
|
];
|
||||||
|
|
||||||
// embedded meta data
|
// embedded meta data
|
||||||
|
case 'UserPreference':
|
||||||
|
return [
|
||||||
|
'name' => 'string',
|
||||||
|
'value' => '@string',
|
||||||
|
];
|
||||||
|
|
||||||
case 'CustomerMeta':
|
case 'CustomerMeta':
|
||||||
case 'ProjectMeta':
|
case 'ProjectMeta':
|
||||||
case 'ActivityMeta':
|
case 'ActivityMeta':
|
||||||
@@ -321,6 +327,7 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
|
|||||||
'timezone' => 'string',
|
'timezone' => 'string',
|
||||||
'accountNumber' => '@string',
|
'accountNumber' => '@string',
|
||||||
'memberships' => ['result' => 'array', 'type' => 'TeamMembership'],
|
'memberships' => ['result' => 'array', 'type' => 'TeamMembership'],
|
||||||
|
'preferences' => ['result' => 'array', 'type' => 'UserPreference'],
|
||||||
];
|
];
|
||||||
|
|
||||||
// if a team is embedded
|
// if a team is embedded
|
||||||
|
|||||||
Reference in New Issue
Block a user