prevent duplicate if overlapping records are disabled (#2311)
This commit is contained in:
@@ -11,8 +11,10 @@ APP_SECRET=change_this_to_something_unique
|
|||||||
|
|
||||||
###> doctrine/doctrine-bundle ###
|
###> doctrine/doctrine-bundle ###
|
||||||
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
# 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"
|
# 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=mysql://db_user:db_password@127.0.0.1:3306/db_name
|
||||||
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data/kimai.sqlite
|
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data/kimai.sqlite
|
||||||
###< doctrine/doctrine-bundle ###
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -19,6 +19,7 @@ php.ini
|
|||||||
public/avatars/*.png
|
public/avatars/*.png
|
||||||
|
|
||||||
templates/invoice/renderer/.~lock*
|
templates/invoice/renderer/.~lock*
|
||||||
|
translations/branding.en.xlf
|
||||||
|
|
||||||
/var/data/*
|
/var/data/*
|
||||||
!/var/data/.gitkeep
|
!/var/data/.gitkeep
|
||||||
|
|||||||
3188
composer.lock
generated
3188
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ doctrine:
|
|||||||
default:
|
default:
|
||||||
# existing migrations will fail if the schema filter is activated
|
# existing migrations will fail if the schema filter is activated
|
||||||
#schema_filter: ~^(?!(bundle_migration_|kimai2_sessions))~
|
#schema_filter: ~^(?!(bundle_migration_|kimai2_sessions))~
|
||||||
|
# Removing "resolve:" would fail eg. SQLite URLs
|
||||||
url: '%env(resolve:DATABASE_URL)%'
|
url: '%env(resolve:DATABASE_URL)%'
|
||||||
driver: 'pdo_mysql'
|
driver: 'pdo_mysql'
|
||||||
# this setting prevents automatic database detection and finds a lot of false-negatives on doctrine:migrations:diff
|
# this setting prevents automatic database detection and finds a lot of false-negatives on doctrine:migrations:diff
|
||||||
|
|||||||
@@ -495,7 +495,7 @@ class TimesheetRepository extends EntityRepository
|
|||||||
|
|
||||||
// yes, we only want to compare the day, not the time
|
// yes, we only want to compare the day, not the time
|
||||||
if ((int) $end->format('Ymd') < (int) $newDateBegin->format('Ymd')) {
|
if ((int) $end->format('Ymd') < (int) $newDateBegin->format('Ymd')) {
|
||||||
break 1;
|
break;
|
||||||
}
|
}
|
||||||
} while ($dateKey !== $dateKeyEnd);
|
} while ($dateKey !== $dateKeyEnd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
namespace App\Voter;
|
namespace App\Voter;
|
||||||
|
|
||||||
|
use App\Configuration\SystemConfiguration;
|
||||||
use App\Entity\Timesheet;
|
use App\Entity\Timesheet;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
use App\Security\RolePermissionManager;
|
use App\Security\RolePermissionManager;
|
||||||
@@ -47,6 +48,9 @@ final class TimesheetVoter extends Voter
|
|||||||
'duplicate'
|
'duplicate'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private $configuration;
|
||||||
|
private $cacheAllowCopy;
|
||||||
|
|
||||||
private $permissionManager;
|
private $permissionManager;
|
||||||
private $lockdownService;
|
private $lockdownService;
|
||||||
|
|
||||||
@@ -55,10 +59,11 @@ final class TimesheetVoter extends Voter
|
|||||||
private $editExported;
|
private $editExported;
|
||||||
private $now;
|
private $now;
|
||||||
|
|
||||||
public function __construct(RolePermissionManager $permissionManager, LockdownService $lockdownService)
|
public function __construct(RolePermissionManager $permissionManager, LockdownService $lockdownService, SystemConfiguration $configuration)
|
||||||
{
|
{
|
||||||
$this->permissionManager = $permissionManager;
|
$this->permissionManager = $permissionManager;
|
||||||
$this->lockdownService = $lockdownService;
|
$this->lockdownService = $lockdownService;
|
||||||
|
$this->configuration = $configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,6 +209,17 @@ final class TimesheetVoter extends Voter
|
|||||||
|
|
||||||
protected function canDuplicate(User $user, Timesheet $timesheet): bool
|
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)) {
|
if (!$this->isAllowedInLockdown($user, $timesheet)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
15
symfony.lock
15
symfony.lock
@@ -120,6 +120,9 @@
|
|||||||
"ref": "bb31a3bbec00a8fc8aa1c9fbf9b0ef9fc492f93d"
|
"ref": "bb31a3bbec00a8fc8aa1c9fbf9b0ef9fc492f93d"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"friendsofphp/proxy-manager-lts": {
|
||||||
|
"version": "v1.0.3"
|
||||||
|
},
|
||||||
"friendsofsymfony/rest-bundle": {
|
"friendsofsymfony/rest-bundle": {
|
||||||
"version": "2.2",
|
"version": "2.2",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
@@ -177,6 +180,15 @@
|
|||||||
"kimai/user-bundle": {
|
"kimai/user-bundle": {
|
||||||
"version": "dev-master"
|
"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": {
|
"laravolt/avatar": {
|
||||||
"version": "3.0.0"
|
"version": "3.0.0"
|
||||||
},
|
},
|
||||||
@@ -285,6 +297,9 @@
|
|||||||
"phpspec/prophecy": {
|
"phpspec/prophecy": {
|
||||||
"version": "1.7.3"
|
"version": "1.7.3"
|
||||||
},
|
},
|
||||||
|
"phpstan/phpdoc-parser": {
|
||||||
|
"version": "0.4.10"
|
||||||
|
},
|
||||||
"phpstan/phpstan": {
|
"phpstan/phpstan": {
|
||||||
"version": "0.11.7"
|
"version": "0.11.7"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
{% macro customers(view) %}
|
{% macro customers(view) %}
|
||||||
{% import "macros/widgets.html.twig" as widgets %}
|
{% import "macros/widgets.html.twig" as widgets %}
|
||||||
|
|
||||||
{% set actions = {'search': {'class': 'search-toggle visible-xs-inline'}, 'visibility': '#modal_customer_admin'} %}
|
{% set actions = {
|
||||||
|
'search': {'class': 'search-toggle visible-xs-inline'},
|
||||||
{% set actions = actions|merge({'download': {'url': path('customer_export'), 'class': 'toolbar-action'}}) %}
|
'visibility': {'modal': '#modal_customer_admin'},
|
||||||
|
'download': {'url': path('customer_export'), 'class': 'toolbar-action'}
|
||||||
|
} %}
|
||||||
|
|
||||||
{% if is_granted('create_customer') %}
|
{% if is_granted('create_customer') %}
|
||||||
{% set actions = actions|merge({'create': {'url': path('admin_customer_create'), 'class': 'modal-ajax-form'}}) %}
|
{% set actions = actions|merge({'create': {'url': path('admin_customer_create'), 'class': 'modal-ajax-form'}}) %}
|
||||||
|
|||||||
@@ -210,11 +210,12 @@ class TimesheetVoterTest extends AbstractVoterTest
|
|||||||
'lockdown_period_start' => $lockdownBegin,
|
'lockdown_period_start' => $lockdownBegin,
|
||||||
'lockdown_period_end' => $lockdownEnd,
|
'lockdown_period_end' => $lockdownEnd,
|
||||||
'lockdown_grace_period' => $lockdownGrace,
|
'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);
|
self::assertInstanceOf(Voter::class, $voter);
|
||||||
|
|
||||||
return $voter;
|
return $voter;
|
||||||
|
|||||||
Reference in New Issue
Block a user