lock exported timesheets (#798)
This commit is contained in:
@@ -616,4 +616,52 @@ class TimesheetController extends BaseApiController
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch the export state of a timesheet record to (un-)lock it
|
||||
*
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Switches the exported state on the record and therefor locks / unlocks it for further updates. Needs edit_export_*_timesheet permission.",
|
||||
* @SWG\Schema(ref="#/definitions/TimesheetEntity")
|
||||
* )
|
||||
* @SWG\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* type="integer",
|
||||
* description="Timesheet record ID to switch export state",
|
||||
* required=true,
|
||||
* )
|
||||
*
|
||||
* @Security("is_granted('edit_export_own_timesheet') or is_granted('edit_export_other_timesheet')")
|
||||
*
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function exportAction($id)
|
||||
{
|
||||
/** @var Timesheet $timesheet */
|
||||
$timesheet = $this->repository->find($id);
|
||||
|
||||
if (null === $timesheet) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (!$this->isGranted('edit_export', $timesheet)) {
|
||||
throw new AccessDeniedHttpException(
|
||||
sprintf('You are not allowed to %s this timesheet', ($timesheet->isExported() ? 'unlock' : 'lock'))
|
||||
);
|
||||
}
|
||||
|
||||
$timesheet->setExported(!$timesheet->isExported());
|
||||
|
||||
$entityManager = $this->getDoctrine()->getManager();
|
||||
$entityManager->persist($timesheet);
|
||||
$entityManager->flush();
|
||||
|
||||
$view = new View($timesheet, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
/**
|
||||
* Command used to create a release package with pre-installed composer, SQLite database and user.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CreateReleaseCommand extends Command
|
||||
{
|
||||
|
||||
@@ -37,6 +37,7 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
* Command used to import data from a Kimai v1 installation.
|
||||
* Getting help in improving this script would be fantastic, it currently only handles the most basic use-cases.
|
||||
*
|
||||
* This command is way to messy and complex to be tested ... so we use something, which I actually don't like:
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class KimaiImporterCommand extends Command
|
||||
|
||||
@@ -19,6 +19,11 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
/**
|
||||
* Command used to execute all the basic application bootstrapping AFTER "composer install" was executed.
|
||||
*
|
||||
* This command is NOT used during runtime and only meant for developers on their local machines.
|
||||
* I am too lazy to think about how this could be tested ... and this is one of the rare edge cases where I don't
|
||||
* feel like it is necessary, so I "cheat" with:
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ResetCommand extends Command
|
||||
{
|
||||
|
||||
@@ -93,6 +93,7 @@ class Extensions extends AbstractExtension
|
||||
'debug' => 'far fa-file-alt',
|
||||
'profile-stats' => 'far fa-chart-bar',
|
||||
'profile' => 'fas fa-user-edit',
|
||||
'warning' => 'fas fa-exclamation-triangle',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,12 +85,24 @@ class TimesheetVoter extends AbstractVoter
|
||||
$permission .= $attribute;
|
||||
break;
|
||||
|
||||
case self::EDIT:
|
||||
if (!$this->canEdit($user, $subject)) {
|
||||
return false;
|
||||
}
|
||||
$permission .= $attribute;
|
||||
break;
|
||||
|
||||
case self::DELETE:
|
||||
if (!$this->canDelete($user, $subject)) {
|
||||
return false;
|
||||
}
|
||||
$permission .= $attribute;
|
||||
break;
|
||||
|
||||
case self::VIEW_RATE:
|
||||
case self::EDIT_RATE:
|
||||
case self::STOP:
|
||||
case self::EDIT:
|
||||
case self::VIEW:
|
||||
case self::DELETE:
|
||||
case self::EXPORT:
|
||||
case self::EDIT_EXPORT:
|
||||
$permission .= $attribute;
|
||||
@@ -114,11 +126,7 @@ class TimesheetVoter extends AbstractVoter
|
||||
return $this->hasRolePermission($user, $permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Timesheet $timesheet
|
||||
* @return bool
|
||||
*/
|
||||
protected function canStart(Timesheet $timesheet)
|
||||
protected function canStart(Timesheet $timesheet): bool
|
||||
{
|
||||
// possible improvements for the future:
|
||||
// we could check the amount of active entries (maybe slow)
|
||||
@@ -142,4 +150,22 @@ class TimesheetVoter extends AbstractVoter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function canEdit(User $user, Timesheet $timesheet): bool
|
||||
{
|
||||
if ($timesheet->isExported() && !$this->hasRolePermission($user, 'edit_exported_timesheet')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function canDelete(User $user, Timesheet $timesheet): bool
|
||||
{
|
||||
if ($timesheet->isExported() && !$this->hasRolePermission($user, 'edit_exported_timesheet')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user