Team API docs (#5897)
* let view_team permission be handled by global ACLs * code style and API docs * improve permission check
This commit is contained in:
@@ -71,7 +71,7 @@ final class TeamController extends BaseApiController
|
||||
* Fetch team
|
||||
*/
|
||||
#[IsGranted('view_team')]
|
||||
#[OA\Response(response: 200, description: 'Returns one team entity', content: new OA\JsonContent(ref: '#/components/schemas/Team'))]
|
||||
#[OA\Response(response: 200, description: 'Returns the team', content: new OA\JsonContent(ref: '#/components/schemas/Team'))]
|
||||
#[Route(methods: ['GET'], path: '/{id}', name: 'get_team', requirements: ['id' => '\d+'])]
|
||||
public function getAction(Team $team): Response
|
||||
{
|
||||
@@ -84,8 +84,8 @@ final class TeamController extends BaseApiController
|
||||
/**
|
||||
* Delete team
|
||||
*/
|
||||
#[IsGranted('delete_team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 204, description: 'Delete one team')])]
|
||||
#[IsGranted('delete', 'team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 204, description: 'Empty')])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'Team ID to delete', required: true)]
|
||||
#[Route(methods: ['DELETE'], path: '/{id}', name: 'delete_team', requirements: ['id' => '\d+'])]
|
||||
public function deleteAction(Team $team): Response
|
||||
@@ -129,7 +129,7 @@ final class TeamController extends BaseApiController
|
||||
/**
|
||||
* Update team
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Patch(description: 'Update an existing team, you can pass all or just a subset of all attributes (passing members will replace all existing ones)', responses: [new OA\Response(response: 200, description: 'Returns the updated team', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/TeamEditForm'))]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'Team ID to update', required: true)]
|
||||
@@ -169,7 +169,7 @@ final class TeamController extends BaseApiController
|
||||
/**
|
||||
* Add team member
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Post(responses: [new OA\Response(response: 200, description: 'Adds a new user to a team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'The team which will receive the new member', required: true)]
|
||||
#[OA\Parameter(name: 'userId', in: 'path', description: 'The team member to add (User ID)', required: true)]
|
||||
@@ -193,7 +193,7 @@ final class TeamController extends BaseApiController
|
||||
/**
|
||||
* Remove team member
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 200, description: 'Removes a user from the team. The teamlead cannot be removed.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'The team from which the member will be removed', required: true)]
|
||||
#[OA\Parameter(name: 'userId', in: 'path', description: 'The team member to remove (User ID)', required: true)]
|
||||
@@ -219,10 +219,12 @@ final class TeamController extends BaseApiController
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant team access to customer
|
||||
* Grant customer access
|
||||
*
|
||||
* The team is granted access to the customer.
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[OA\Post(responses: [new OA\Response(response: 200, description: 'Adds a new customer to a team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Post(responses: [new OA\Response(response: 200, description: 'Returns the team including the customer', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'The team that is granted access', required: true)]
|
||||
#[OA\Parameter(name: 'customerId', in: 'path', description: 'The customer to grant acecess to (Customer ID)', required: true)]
|
||||
#[Route(methods: ['POST'], path: '/{id}/customers/{customerId}', name: 'post_team_customer', requirements: ['id' => '\d+', 'customerId' => '\d+'])]
|
||||
@@ -242,10 +244,12 @@ final class TeamController extends BaseApiController
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke customer access from team
|
||||
* Revoke customer access
|
||||
*
|
||||
* This removes access to the customer from the team.
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 200, description: 'Removes a customer from the team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 200, description: 'Returns the team without the customer', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'The team whose permission will be revoked', required: true)]
|
||||
#[OA\Parameter(name: 'customerId', in: 'path', description: 'The customer to remove (Customer ID)', required: true)]
|
||||
#[Route(methods: ['DELETE'], path: '/{id}/customers/{customerId}', name: 'delete_team_customer', requirements: ['id' => '\d+', 'customerId' => '\d+'])]
|
||||
@@ -265,10 +269,12 @@ final class TeamController extends BaseApiController
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant team access to project
|
||||
* Grant project access
|
||||
*
|
||||
* The team is granted access to the project.
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[OA\Post(responses: [new OA\Response(response: 200, description: 'Adds a new project to a team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Post(responses: [new OA\Response(response: 200, description: 'Returns the team including the project', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'The team that is granted access', required: true)]
|
||||
#[OA\Parameter(name: 'projectId', in: 'path', description: 'The project to grant acecess to (Project ID)', required: true)]
|
||||
#[Route(methods: ['POST'], path: '/{id}/projects/{projectId}', name: 'post_team_project', requirements: ['id' => '\d+', 'projectId' => '\d+'])]
|
||||
@@ -288,10 +294,12 @@ final class TeamController extends BaseApiController
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke project access from team
|
||||
* Revoke project access
|
||||
*
|
||||
* This removes access to the project from the team.
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 200, description: 'Removes a project from the team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 200, description: 'Returns the team without the project', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'The team whose permission will be revoked', required: true)]
|
||||
#[OA\Parameter(name: 'projectId', in: 'path', description: 'The project to remove (Project ID)', required: true)]
|
||||
#[Route(methods: ['DELETE'], path: '/{id}/projects/{projectId}', name: 'delete_team_project', requirements: ['id' => '\d+', 'projectId' => '\d+'])]
|
||||
@@ -311,10 +319,12 @@ final class TeamController extends BaseApiController
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant team access to activity
|
||||
* Grant activity access
|
||||
*
|
||||
* The team is granted access to the activity.
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[OA\Post(responses: [new OA\Response(response: 200, description: 'Adds a new activity to a team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Post(responses: [new OA\Response(response: 200, description: 'Returns the team including the activity', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'The team that is granted access', required: true)]
|
||||
#[OA\Parameter(name: 'activityId', in: 'path', description: 'The activity to grant acecess to (Activity ID)', required: true)]
|
||||
#[Route(methods: ['POST'], path: '/{id}/activities/{activityId}', name: 'post_team_activity', requirements: ['id' => '\d+', 'activityId' => '\d+'])]
|
||||
@@ -334,10 +344,12 @@ final class TeamController extends BaseApiController
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke activity access from team
|
||||
* Revoke activity access
|
||||
*
|
||||
* This removes access to the activity from the team.
|
||||
*/
|
||||
#[IsGranted('edit_team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 200, description: 'Removes a activity from the team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[IsGranted('edit', 'team')]
|
||||
#[OA\Delete(responses: [new OA\Response(response: 200, description: 'Returns the team without the activity', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])]
|
||||
#[OA\Parameter(name: 'id', in: 'path', description: 'The team whose permission will be revoked', required: true)]
|
||||
#[OA\Parameter(name: 'activityId', in: 'path', description: 'The activity to remove (Activity ID)', required: true)]
|
||||
#[Route(methods: ['DELETE'], path: '/{id}/activities/{activityId}', name: 'delete_team_activity', requirements: ['id' => '\d+', 'activityId' => '\d+'])]
|
||||
|
||||
@@ -38,15 +38,9 @@ final class TeamController extends AbstractController
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TeamRepository $repository
|
||||
* @param Request $request
|
||||
* @param int $page
|
||||
* @return Response
|
||||
*/
|
||||
#[Route(path: '/', defaults: ['page' => 1], name: 'admin_team', methods: ['GET'])]
|
||||
#[Route(path: '/page/{page}', requirements: ['page' => '[1-9]\d*'], name: 'admin_team_paginated', methods: ['GET'])]
|
||||
public function listTeams(TeamRepository $repository, Request $request, $page): Response
|
||||
public function listTeams(int $page, TeamRepository $repository, Request $request): Response
|
||||
{
|
||||
$query = new TeamQuery();
|
||||
$query->setPage($page);
|
||||
@@ -81,10 +75,6 @@ final class TeamController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
#[Route(path: '/create', name: 'admin_team_create', methods: ['GET', 'POST'])]
|
||||
#[IsGranted('create_team')]
|
||||
public function createTeam(Request $request): Response
|
||||
|
||||
@@ -24,7 +24,6 @@ final class TeamVoter extends Voter
|
||||
* support rules based on the given $subject (here: Team)
|
||||
*/
|
||||
private const ALLOWED_ATTRIBUTES = [
|
||||
'view',
|
||||
'edit',
|
||||
'delete',
|
||||
];
|
||||
@@ -52,17 +51,13 @@ final class TeamVoter extends Voter
|
||||
{
|
||||
$user = $token->getUser();
|
||||
|
||||
if (!$user instanceof User) {
|
||||
if (!$user instanceof User || !($subject instanceof Team)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($attribute) {
|
||||
case 'edit':
|
||||
case 'delete':
|
||||
// changing existing teams should be limited to admins and teamleads
|
||||
if (!$user->isAdmin() && !$user->isSuperAdmin() && !$user->isTeamleadOf($subject)) {
|
||||
return false;
|
||||
}
|
||||
// changing existing teams should be limited to admins and teamleads
|
||||
if (!$user->isAdmin() && !$user->isSuperAdmin() && !$user->isTeamleadOf($subject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->permissionManager->hasRolePermission($user, $attribute . '_team');
|
||||
|
||||
Reference in New Issue
Block a user