prevent duplicate if overlapping records are disabled (#2311)

This commit is contained in:
Kevin Papst
2021-02-06 17:31:14 +01:00
committed by GitHub
parent 8d41fa20bd
commit 9eb25c412e
9 changed files with 2110 additions and 1130 deletions

View File

@@ -11,8 +11,10 @@ APP_SECRET=change_this_to_something_unique
###> doctrine/doctrine-bundle ###
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# For a MySQL database, use: "mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=10.2.12&charset=utf8"
# For a MariaDB database, use: "mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=mariadb-10.2.12"
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data/kimai.sqlite"
# Configure your db driver and server_version in config/packages/doctrine.yaml
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
# DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data/kimai.sqlite
###< doctrine/doctrine-bundle ###

1
.gitignore vendored
View File

@@ -19,6 +19,7 @@ php.ini
public/avatars/*.png
templates/invoice/renderer/.~lock*
translations/branding.en.xlf
/var/data/*
!/var/data/.gitkeep

3188
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@ doctrine:
default:
# existing migrations will fail if the schema filter is activated
#schema_filter: ~^(?!(bundle_migration_|kimai2_sessions))~
# Removing "resolve:" would fail eg. SQLite URLs
url: '%env(resolve:DATABASE_URL)%'
driver: 'pdo_mysql'
# this setting prevents automatic database detection and finds a lot of false-negatives on doctrine:migrations:diff

View File

@@ -495,7 +495,7 @@ class TimesheetRepository extends EntityRepository
// yes, we only want to compare the day, not the time
if ((int) $end->format('Ymd') < (int) $newDateBegin->format('Ymd')) {
break 1;
break;
}
} while ($dateKey !== $dateKeyEnd);
}

View File

@@ -9,6 +9,7 @@
namespace App\Voter;
use App\Configuration\SystemConfiguration;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Security\RolePermissionManager;
@@ -47,6 +48,9 @@ final class TimesheetVoter extends Voter
'duplicate'
];
private $configuration;
private $cacheAllowCopy;
private $permissionManager;
private $lockdownService;
@@ -55,10 +59,11 @@ final class TimesheetVoter extends Voter
private $editExported;
private $now;
public function __construct(RolePermissionManager $permissionManager, LockdownService $lockdownService)
public function __construct(RolePermissionManager $permissionManager, LockdownService $lockdownService, SystemConfiguration $configuration)
{
$this->permissionManager = $permissionManager;
$this->lockdownService = $lockdownService;
$this->configuration = $configuration;
}
/**
@@ -204,6 +209,17 @@ final class TimesheetVoter extends Voter
protected function canDuplicate(User $user, Timesheet $timesheet): bool
{
if ($this->cacheAllowCopy === null) {
$this->cacheAllowCopy = $this->configuration->isTimesheetAllowOverlappingRecords();
}
// This is a quickfix, because the API cannot open dialogs. if the method is copied to the timesheet controller,
// we could open the edit dialog instead of directly saving the copied entry.
// Probably add a new permission is required to differentiate between API and UI.
if (!$this->cacheAllowCopy) {
return false;
}
if (!$this->isAllowedInLockdown($user, $timesheet)) {
return false;
}

View File

@@ -120,6 +120,9 @@
"ref": "bb31a3bbec00a8fc8aa1c9fbf9b0ef9fc492f93d"
}
},
"friendsofphp/proxy-manager-lts": {
"version": "v1.0.3"
},
"friendsofsymfony/rest-bundle": {
"version": "2.2",
"recipe": {
@@ -177,6 +180,15 @@
"kimai/user-bundle": {
"version": "dev-master"
},
"laminas/laminas-code": {
"version": "3.4.1"
},
"laminas/laminas-eventmanager": {
"version": "3.2.1"
},
"laminas/laminas-zendframework-bridge": {
"version": "1.1.1"
},
"laravolt/avatar": {
"version": "3.0.0"
},
@@ -285,6 +297,9 @@
"phpspec/prophecy": {
"version": "1.7.3"
},
"phpstan/phpdoc-parser": {
"version": "0.4.10"
},
"phpstan/phpstan": {
"version": "0.11.7"
},

View File

@@ -1,9 +1,11 @@
{% macro customers(view) %}
{% import "macros/widgets.html.twig" as widgets %}
{% set actions = {'search': {'class': 'search-toggle visible-xs-inline'}, 'visibility': '#modal_customer_admin'} %}
{% set actions = actions|merge({'download': {'url': path('customer_export'), 'class': 'toolbar-action'}}) %}
{% set actions = {
'search': {'class': 'search-toggle visible-xs-inline'},
'visibility': {'modal': '#modal_customer_admin'},
'download': {'url': path('customer_export'), 'class': 'toolbar-action'}
} %}
{% if is_granted('create_customer') %}
{% set actions = actions|merge({'create': {'url': path('admin_customer_create'), 'class': 'modal-ajax-form'}}) %}

View File

@@ -210,11 +210,12 @@ class TimesheetVoterTest extends AbstractVoterTest
'lockdown_period_start' => $lockdownBegin,
'lockdown_period_end' => $lockdownEnd,
'lockdown_grace_period' => $lockdownGrace,
'allow_overlapping_records' => true,
],
]
]);
$voter = new TimesheetVoter($this->getRolePermissionManager(), new LockdownService($config));
$voter = new TimesheetVoter($this->getRolePermissionManager(), new LockdownService($config), $config);
self::assertInstanceOf(Voter::class, $voter);
return $voter;