permissionManager = $permissionManager; $this->lockdownService = $lockdownService; } /** * @param string $attribute * @param mixed $subject * @return bool */ protected function supports($attribute, $subject) { if (!($subject instanceof Timesheet)) { return false; } if (!\in_array($attribute, self::ALLOWED_ATTRIBUTES)) { return false; } return true; } /** * @param string $attribute * @param Timesheet $subject * @param TokenInterface $token * @return bool */ protected function voteOnAttribute($attribute, $subject, TokenInterface $token) { $user = $token->getUser(); if (!($user instanceof User)) { return false; } $permission = ''; switch ($attribute) { case self::START: if (!$this->canStart($subject)) { return false; } $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 'duplicate': if (!$this->canDuplicate($user, $subject)) { return false; } $permission = self::EDIT; break; case self::VIEW_RATE: case self::EDIT_RATE: case self::STOP: case self::VIEW: case self::EXPORT: case self::EDIT_EXPORT: $permission .= $attribute; break; default: return false; } $permission .= '_'; // extend me for "team" support later on if ($subject->getUser()->getId() == $user->getId()) { $permission .= 'own'; } else { $permission .= 'other'; } $permission .= '_timesheet'; return $this->permissionManager->hasRolePermission($user, $permission); } protected function canStart(Timesheet $timesheet): bool { // possible improvements for the future: // we could check the amount of active entries (maybe slow) // if a teamlead starts an entry for another user, check that this user is part of his team (needs to be done for teams) if (null === $timesheet->getActivity()) { return false; } if (null === $timesheet->getProject()) { return false; } if (!$timesheet->getActivity()->isVisible() || !$timesheet->getProject()->isVisible()) { return false; } if (!$timesheet->getProject()->getCustomer()->isVisible()) { return false; } return true; } protected function canEdit(User $user, Timesheet $timesheet): bool { if (!$this->isAllowedExported($user, $timesheet)) { return false; } if (!$this->isAllowedInLockdown($user, $timesheet)) { return false; } return true; } protected function canDelete(User $user, Timesheet $timesheet): bool { if (!$this->isAllowedExported($user, $timesheet)) { return false; } if (!$this->isAllowedInLockdown($user, $timesheet)) { return false; } return true; } protected function canDuplicate(User $user, Timesheet $timesheet): bool { if (!$this->isAllowedInLockdown($user, $timesheet)) { return false; } return true; } private function isAllowedExported(User $user, Timesheet $timesheet): bool { if (!$timesheet->isExported()) { return true; } if ($this->editExported === null) { $this->editExported = $this->permissionManager->hasRolePermission($user, 'edit_exported_timesheet'); } return $this->editExported; } private function isAllowedInLockdown(User $user, Timesheet $timesheet): bool { if (!$this->lockdownService->isLockdownActive()) { return true; } if ($this->lockdownOverride === null) { $this->lockdownOverride = $this->permissionManager->hasRolePermission($user, 'lockdown_override_timesheet'); } if ($this->lockdownOverride) { return true; } if ($this->lockdownGrace === null) { $this->lockdownGrace = $this->permissionManager->hasRolePermission($user, 'lockdown_grace_timesheet'); } if ($this->now === null) { $this->now = new \DateTime('now', new \DateTimeZone($user->getTimezone())); } return $this->lockdownService->isEditable($timesheet, $this->now, $this->lockdownGrace); } }