release 0.8 (#567)

This commit is contained in:
Kevin Papst
2019-02-19 11:03:11 +01:00
committed by GitHub
parent b4f1cae323
commit 47b7046743
40 changed files with 446 additions and 341 deletions

View File

@@ -1,22 +0,0 @@
## Description
## Expected Behavior
## Actual Behavior
## Possible Fix
## Steps to Reproduce
1.
2.
3.
4.
## Your Environment
* Version:
* Browser Name and version:
* Operating System and version (desktop or mobile):

View File

@@ -1,6 +1,6 @@
---
name: Bug report
about: Create a report to help us improve
about: Create a report to help us improve Kimai
---
@@ -11,25 +11,24 @@ A clear and concise description of what the bug is.
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
3. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Logfile**
```
Add the last lines from your logfile at var/log/prod.log, around the time when the problem happened.
```
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
**Desktop/Smartphone**
Please complete the following information if this seems to be a frontend issue:
- Device: [e.g. iPhone6s]
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
- Kimai version
- PHP version

View File

@@ -1,6 +1,6 @@
---
name: Feature request
about: Suggest an idea for this project
about: Suggest an idea to make Kimai better
---

View File

@@ -1,5 +1,5 @@
## Description
A clear and concise description of what this pull request changes.
## Types of changes
- [ ] Bug fix (non-breaking change which fixes an issue)
@@ -7,8 +7,7 @@
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
## Checklist
- [ ] My code follows the code style
- [ ] All files have a license header
- [ ] All methods have a doc header with type declarations
- [ ] I have executed `bin/console kimai:phpcs --fix` to make sure my changes adopt the correct code style
- [ ] I have updated the documentation accordingly
- [ ] I have added tests to cover my changes
- [ ] I agree that this code is used in Kimai and will be published under the [MIT license](https://github.com/kevinpapst/kimai2/blob/master/LICENSE)

View File

@@ -1,4 +1,4 @@
unreleased=true
future-release=0.7
future-release=0.8
exclude-labels=duplicate,question,invalid,wontfix,release
enhancement_labels=>enhancement,Enhancement,feature request

View File

@@ -1,5 +1,63 @@
# Change Log
## [0.8](https://github.com/kevinpapst/kimai2/tree/0.8) (2019-02-19)
[Full Changelog](https://github.com/kevinpapst/kimai2/compare/0.7...0.8)
**Implemented enhancements:**
- Export other users' timesheets using the API [\#562](https://github.com/kevinpapst/kimai2/issues/562)
- Some importer bugs/improvements [\#553](https://github.com/kevinpapst/kimai2/issues/553)
- Export timesheet only exports entries on the current page [\#534](https://github.com/kevinpapst/kimai2/issues/534)
- On the last activities dropdown show tha last ten DIFFERENT activities [\#533](https://github.com/kevinpapst/kimai2/issues/533)
- Better user expierence on "My Times" [\#526](https://github.com/kevinpapst/kimai2/issues/526)
- Highlight current day in datepickers and not only the selected day [\#522](https://github.com/kevinpapst/kimai2/issues/522)
- Configuration of first page after login [\#501](https://github.com/kevinpapst/kimai2/issues/501)
- Visual Grouping of entry from same day or same week with some stats of that group [\#495](https://github.com/kevinpapst/kimai2/issues/495)
- add currency field to invoice template [\#422](https://github.com/kevinpapst/kimai2/issues/422)
**Fixed bugs:**
- Error 404 on 'My times' page 2+ if the time range is changed to something smaller [\#558](https://github.com/kevinpapst/kimai2/issues/558)
- Timezone is not working correctly [\#554](https://github.com/kevinpapst/kimai2/issues/554)
- New time picker not working on languages without updated translation [\#546](https://github.com/kevinpapst/kimai2/issues/546)
- Export timesheet only exports entries on the current page [\#534](https://github.com/kevinpapst/kimai2/issues/534)
- Kimai2 will not allow me to enter times in the future [\#531](https://github.com/kevinpapst/kimai2/issues/531)
- No projects in filter section [\#525](https://github.com/kevinpapst/kimai2/issues/525)
- This value should be greater than or equal to zero [\#511](https://github.com/kevinpapst/kimai2/issues/511)
- Wrong time after migration kimai v1 data [\#507](https://github.com/kevinpapst/kimai2/issues/507)
- SQL-Error for getRecentActivities\(\) caused by GROUP BY [\#488](https://github.com/kevinpapst/kimai2/issues/488)
**Closed issues:**
- Feedback for improving installation setup [\#541](https://github.com/kevinpapst/kimai2/issues/541)
- template entry.end\_time shows empty field [\#535](https://github.com/kevinpapst/kimai2/issues/535)
- Global Projects [\#413](https://github.com/kevinpapst/kimai2/issues/413)
**Merged pull requests:**
- handle deleted user during import from v1 [\#569](https://github.com/kevinpapst/kimai2/pull/569) ([kevinpapst](https://github.com/kevinpapst))
- fix pagination in combination with daterange picker [\#568](https://github.com/kevinpapst/kimai2/pull/568) ([kevinpapst](https://github.com/kevinpapst))
- allow to query other users timesheets via api [\#563](https://github.com/kevinpapst/kimai2/pull/563) ([kevinpapst](https://github.com/kevinpapst))
- Updated HTML invoice templates [\#560](https://github.com/kevinpapst/kimai2/pull/560) ([kevinpapst](https://github.com/kevinpapst))
- updated composer packages [\#559](https://github.com/kevinpapst/kimai2/pull/559) ([kevinpapst](https://github.com/kevinpapst))
- fix timezone problems in timesheet forms [\#555](https://github.com/kevinpapst/kimai2/pull/555) ([kevinpapst](https://github.com/kevinpapst))
- Daily stats in timesheet [\#552](https://github.com/kevinpapst/kimai2/pull/552) ([kevinpapst](https://github.com/kevinpapst))
- Added more php requirements to documentation [\#551](https://github.com/kevinpapst/kimai2/pull/551) ([infeeeee](https://github.com/infeeeee))
- improve recent activities [\#550](https://github.com/kevinpapst/kimai2/pull/550) ([kevinpapst](https://github.com/kevinpapst))
- scss fixes: year selector width, dropdown menu width, navbar refactoring [\#549](https://github.com/kevinpapst/kimai2/pull/549) ([infeeeee](https://github.com/infeeeee))
- improved installation docs [\#548](https://github.com/kevinpapst/kimai2/pull/548) ([kevinpapst](https://github.com/kevinpapst))
- fix daterange-picker for fr, hu and ar [\#547](https://github.com/kevinpapst/kimai2/pull/547) ([kevinpapst](https://github.com/kevinpapst))
- do not limit users timesheet export page size [\#545](https://github.com/kevinpapst/kimai2/pull/545) ([kevinpapst](https://github.com/kevinpapst))
- Use Symfony formatter for currency symbol placement [\#542](https://github.com/kevinpapst/kimai2/pull/542) ([sanjitlpatel](https://github.com/sanjitlpatel))
- Localized date-inputs and daterange-picker [\#540](https://github.com/kevinpapst/kimai2/pull/540) ([kevinpapst](https://github.com/kevinpapst))
- added export module [\#538](https://github.com/kevinpapst/kimai2/pull/538) ([kevinpapst](https://github.com/kevinpapst))
- updated documentation [\#536](https://github.com/kevinpapst/kimai2/pull/536) ([kevinpapst](https://github.com/kevinpapst))
- support remote data in beta-test selectpicker [\#529](https://github.com/kevinpapst/kimai2/pull/529) ([kevinpapst](https://github.com/kevinpapst))
- Improve allowed running records [\#528](https://github.com/kevinpapst/kimai2/pull/528) ([kevinpapst](https://github.com/kevinpapst))
- Improve daterangepicker [\#527](https://github.com/kevinpapst/kimai2/pull/527) ([kevinpapst](https://github.com/kevinpapst))
- added configurable view after login [\#523](https://github.com/kevinpapst/kimai2/pull/523) ([kevinpapst](https://github.com/kevinpapst))
- convert timesheets to UTC with support for user timezone [\#372](https://github.com/kevinpapst/kimai2/pull/372) ([kevinpapst](https://github.com/kevinpapst))
## [0.7](https://github.com/kevinpapst/kimai2/tree/0.7) (2019-01-28)
[Full Changelog](https://github.com/kevinpapst/kimai2/compare/0.6.1...0.7)
@@ -18,11 +76,10 @@
- Configuration option to disable fixed rate and hourly rate from "edit timesheet" [\#330](https://github.com/kevinpapst/kimai2/issues/330)
- Set other users hourly rate [\#303](https://github.com/kevinpapst/kimai2/issues/303)
- Feature request - Make "Rate" hideable [\#217](https://github.com/kevinpapst/kimai2/issues/217)
- fixed null project for advanced invoice calculator [\#462](https://github.com/kevinpapst/kimai2/pull/462) ([kevinpapst](https://github.com/kevinpapst))
- fixed null project for advanced invoice calculator [\#462](https://github.com/kevinpapst/kimai2/pull/462) ([kevinpapst](https://github.com/kevinpapst))
**Fixed bugs:**
- This value should be greater than or equal to zero [\#511](https://github.com/kevinpapst/kimai2/issues/511)
- Timesheet Export for Admins [\#503](https://github.com/kevinpapst/kimai2/issues/503)
- admin activity: visibility "none" \(no filter\) causes sql-error [\#491](https://github.com/kevinpapst/kimai2/issues/491)
- login-screen optimizations [\#483](https://github.com/kevinpapst/kimai2/issues/483)
@@ -51,7 +108,7 @@
- pagination without reload while keeping filters applied [\#521](https://github.com/kevinpapst/kimai2/pull/521) ([kevinpapst](https://github.com/kevinpapst))
- go back to calendar after editing and creation of time-records [\#519](https://github.com/kevinpapst/kimai2/pull/519) ([kevinpapst](https://github.com/kevinpapst))
- fetch toolbar results without page reload [\#518](https://github.com/kevinpapst/kimai2/pull/518) ([kevinpapst](https://github.com/kevinpapst))
- fetch toolbar results without page reload [\#518](https://github.com/kevinpapst/kimai2/pull/518) ([kevinpapst](https://github.com/kevinpapst))
- Form and theme improvements [\#513](https://github.com/kevinpapst/kimai2/pull/513) ([kevinpapst](https://github.com/kevinpapst))
- validation for future and negative times [\#512](https://github.com/kevinpapst/kimai2/pull/512) ([kevinpapst](https://github.com/kevinpapst))
- alphabetical order for selectboxes [\#510](https://github.com/kevinpapst/kimai2/pull/510) ([kevinpapst](https://github.com/kevinpapst))

View File

@@ -5,26 +5,30 @@ Database upgrades are currently ONLY provided for MySQL/MariaDB and SQLite.
If you plan on using e.g. PostgreSQL, please read more about the `bin/console doctrine:migrations:diff` and
`bin/console doctrine:migrations:migrate` commands and contact us, so we can integrate them into the official releases.
A normal upgrade can be executed with these commands:
Upgrading to the latest available version can be achieved with these commands:
```bash
git pull origin master
git fetch --tags
git checkout 0.8
sudo -u www-data composer install --no-dev --optimize-autoloader
sudo -u www-data bin/console cache:clear --env=prod
sudo -u www-data bin/console cache:warmup --env=prod
bin/console doctrine:migrations:migrate
```
Be careful when upgrading multiple versions at once: follow each version specific information!
There might be version specific tasks that need to be executed before or after these steps, please see below
if your updated version is mentioned below.
## [0.8](https://github.com/kevinpapst/kimai2/releases/tag/0.8) (unreleased)
There was a change introduced regarding the storage of the date-time objects in timesheet records.
Please read this [Pull request](https://github.com/kevinpapst/kimai2/pull/372) carefully before you follow the instructions
to convert the timezones in your existing time records with `bin/console kimai:convert-timezone --help`.
After you followed the normal update and database migration process (see above), you need to execute a bash command (see below) and check if you want to apply changes to your `local.yaml`.
If you don't do that, you will end up with wrong times in your database. Be especially careful, when you previously imported data from Kimai v1.
- An important change was introduced regarding the storage of date-time objects in the database. Please read this [pull request](https://github.com/kevinpapst/kimai2/pull/372) BEFORE you follow the instructions
to convert the timezones in your existing time records with `bin/console kimai:convert-timezone`. Without that, you will end up with wrong times in your database.
- A new boolean setting `kimai.timesheet.rules.allow_future_times` was introduced
- New [permissions](var/docs/permissions.md) are available: `view_export,create_export,edit_export_own_timesheet,edit_export_other_timesheet,system_information`
## [0.7](https://github.com/kevinpapst/kimai2/releases/tag/0.7) (2019-01-28)
@@ -68,16 +72,6 @@ sudo composer self-update
sudo -u www-data composer update symfony/flex --no-plugins --no-scripts
```
Then the full update can be executed as usual:
```bash
git pull origin master
sudo -u www-data composer install --no-dev --optimize-autoloader
sudo -u www-data bin/console cache:clear --env=prod
sudo -u www-data bin/console cache:warmup --env=prod
bin/console doctrine:migrations:migrate
```
## [0.3](https://github.com/kevinpapst/kimai2/releases/tag/0.3) (2018-07-22)
**Update from 0.2:**

View File

@@ -62,7 +62,6 @@ $(function() {
$('input[data-daterangepickerenable="on"]').each(function(index) {
var localeFormat = $(this).data('format');
var separator = $(this).data('separator');
var transToday = $.kimai.settings['today'];
var rangesList = {};
rangesList[$.kimai.settings['today']] = [moment(), moment()];
rangesList[$.kimai.settings['yesterday']] = [moment().subtract(1, 'days'), moment().subtract(1, 'days')];

View File

@@ -83,11 +83,11 @@ class ActivityController extends BaseApiController
$query->setOrderBy($orderBy);
}
if (null !== ($globals = $paramFetcher->get('globals'))) {
if (null !== $paramFetcher->get('globals')) {
$query->setGlobalsOnly(true);
}
if ('false' === ($globalsFirst = $paramFetcher->get('globalsFirst'))) {
if ('false' === $paramFetcher->get('globalsFirst')) {
$query->setOrderGlobalsFirst(false);
}

View File

@@ -25,6 +25,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
* You should convert all timesheet records that were saved with Kimai 2 directly, but NOT the ones migrated from Kimai v1.
*
* Please read https://github.com/kevinpapst/kimai2/pull/372 to find out more!
*
* @codeCoverageIgnore
*/
class ConvertTimezoneCommand extends Command
{

View File

@@ -35,6 +35,8 @@ 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.
*
* @codeCoverageIgnore
*/
class KimaiImporterCommand extends Command
{
@@ -962,7 +964,6 @@ class KimaiImporterCommand extends Command
// ----------------------- unknown user, damned missing data integrity in Kimai v1 -----------------------
if (!isset($this->users[$oldRecord['userID']])) {
$tempUserName = uniqid();
$tempPassword = uniqid() . uniqid();

View File

@@ -21,7 +21,7 @@ class Constants
/**
* The current release version
*/
public const VERSION = '0.7';
public const VERSION = '0.8';
/**
* The release name, will only change for new major version
*/

View File

@@ -74,5 +74,4 @@ class TimezoneSubscriber implements EventSubscriberInterface
return ($user instanceof User);
}
}

View File

@@ -9,6 +9,7 @@
namespace App\Repository;
use App\Entity\Activity;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Model\Statistic\Month;
@@ -364,8 +365,7 @@ class TimesheetRepository extends AbstractRepository
->setParameter('activity', $query->getActivity());
}
// TODO if activity is an int, this will fail
if (null === $query->getActivity() || null === $query->getActivity()->getProject()) {
if (null === $query->getActivity() || ($query->getActivity() instanceof Activity && null === $query->getActivity()->getProject())) {
if (null !== $query->getProject()) {
$qb->andWhere('t.project = :project')
->setParameter('project', $query->getProject());

View File

@@ -67,7 +67,7 @@ class ActivityControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, $url, 'GET', $parameters);
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(count($expected), count($result));
for ($i = 0; $i < count($result); $i++) {
@@ -93,13 +93,32 @@ class ActivityControllerTest extends APIControllerBaseTest
yield ['/api/activities', ['project' => '2', 'visible' => VisibilityQuery::SHOW_HIDDEN], [[false], [true, 2]]];
}
public function testGetCollectionWithQuery()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$this->loadActivityTestData($client);
$query = ['order' => 'ASC', 'orderBy' => 'project', 'globalsFirst' => 'false'];
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$this->assertAccessIsGranted($client, '/api/activities', 'GET', $query);
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(5, count($result));
$this->assertStructure($result[0], false);
$this->assertEquals(1, $result[2]['project']);
$this->assertEquals(2, $result[3]['project']);
$this->assertEquals(2, $result[4]['project']);
}
public function testGetEntity()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$this->assertAccessIsGranted($client, '/api/activities/1');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$expectedKeys = ['id', 'name', 'comment', 'visible'];
$actual = array_keys($result);

View File

@@ -35,7 +35,7 @@ class ApiDocControllerTest extends ControllerBaseTest
$this->assertAccessIsGranted($client, '/api/doc.json');
$this->assertContains('"title":"Kimai 2 - API Docs"', $client->getResponse()->getContent());
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertNotEmpty($result);
}

View File

@@ -28,7 +28,20 @@ class CustomerControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, '/api/customers');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(1, count($result));
$this->assertStructure($result[0], false);
}
public function testGetCollectionWithQuery()
{
$query = ['order' => 'ASC', 'orderBy' => 'name', 'visible' => 3];
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$this->assertAccessIsGranted($client, '/api/customers', 'GET', $query);
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(1, count($result));
$this->assertStructure($result[0], false);
@@ -40,7 +53,7 @@ class CustomerControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, '/api/customers/1');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertStructure($result, true);
}

View File

@@ -29,7 +29,7 @@ class HealthcheckControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, '/api/ping');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertEquals(['message' => 'pong'], $result);
}
@@ -39,7 +39,7 @@ class HealthcheckControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, '/api/version');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertArrayHasKey('version', $result);
$this->assertArrayHasKey('candidate', $result);

View File

@@ -32,7 +32,7 @@ class ProjectControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, '/api/projects');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(1, count($result));
$this->assertStructure($result[0], false);
@@ -81,7 +81,7 @@ class ProjectControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, $url, 'GET', $parameters);
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertEquals(count($expected), count($result), 'Found wrong amount of projects');
for ($i = 0; $i < count($expected); $i++) {
@@ -111,7 +111,7 @@ class ProjectControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, '/api/projects/1');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertStructure($result);
}

View File

@@ -14,6 +14,7 @@ use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\User;
use App\Tests\DataFixtures\TimesheetFixtures;
use Symfony\Component\HttpFoundation\Response;
/**
* @coversDefaultClass \App\API\TimesheetController
@@ -118,7 +119,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
public function testGetCollectionWithQuery()
{
$query = ['customer' => 1, 'project' => 1, 'page' => 2, 'size' => 5, 'order' => 'DESC', 'orderBy' => 'rate'];
$query = ['customer' => 1, 'project' => 1, 'activity' => 1, 'page' => 2, 'size' => 5, 'order' => 'DESC', 'orderBy' => 'rate'];
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$this->assertAccessIsGranted($client, '/api/timesheets', 'GET', $query);
$result = json_decode($client->getResponse()->getContent(), true);
@@ -218,24 +219,6 @@ class TimesheetControllerTest extends APIControllerBaseTest
$this->assertApiCallValidationError($client->getResponse(), ['activity']);
}
public function testPostActionWithIdIsNotAllowed()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$data = [
'id' => 1,
'activity' => 1,
'project' => 1,
'begin' => (new \DateTime('- 8 hours'))->format('Y-m-d H:m'),
'end' => (new \DateTime())->format('Y-m-d H:m'),
'description' => 'foo',
'fixedRate' => 2016,
'hourlyRate' => 127
];
$this->request($client, '/api/timesheets', 'POST', [], json_encode($data));
$this->assertFalse($client->getResponse()->isSuccessful());
$this->assertEquals(400, $client->getResponse()->getStatusCode());
}
public function testNotFound()
{
$this->assertEntityNotFound(User::ROLE_USER, '/api/timesheets/20');
@@ -263,6 +246,38 @@ class TimesheetControllerTest extends APIControllerBaseTest
$this->assertEquals(1, $result['exported']);
}
public function testPatchActionWithInvalidUser()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
$fixture = new TimesheetFixtures();
$fixture
->setFixedRate(true)
->setHourlyRate(true)
->setAmount(10)
->setUser($this->getUserByRole($em, User::ROLE_TEAMLEAD))
->setStartDate(new \DateTime('-10 days'))
->setAllowEmptyDescriptions(false)
;
$this->importFixture($em, $fixture);
$data = [
'activity' => 1,
'project' => 1,
'begin' => (new \DateTime('- 7 hours'))->format('Y-m-d H:m'),
'end' => (new \DateTime())->format('Y-m-d H:m'),
'description' => 'foo',
'exported' => true,
];
$this->request($client, '/api/timesheets/15', 'PATCH', [], json_encode($data));
$response = $client->getResponse();
$this->assertFalse($response->isSuccessful());
$this->assertEquals(Response::HTTP_FORBIDDEN, $response->getStatusCode());
$json = json_decode($response->getContent(), true);
$this->assertEquals('User cannot update timesheet', $json['message']);
}
public function testInvalidPatchAction()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);

View File

@@ -29,7 +29,7 @@ class UserControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, '/api/users');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(6, count($result));
$this->assertStructure($result[0], false);
@@ -41,7 +41,7 @@ class UserControllerTest extends APIControllerBaseTest
$this->assertAccessIsGranted($client, '/api/users/1');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertStructure($result);
}

View File

@@ -48,7 +48,7 @@ class CalendarControllerTest extends ControllerBaseTest
$response = $client->getResponse();
$this->assertTrue($response->isSuccessful());
$json = json_decode($response->getContent(), true);
$this->assertInternalType('array', $json);
$this->assertIsArray($json);
$this->assertEmpty($json);
}
@@ -68,11 +68,11 @@ class CalendarControllerTest extends ControllerBaseTest
$response = $client->getResponse();
$this->assertTrue($response->isSuccessful());
$json = json_decode($response->getContent(), true);
$this->assertInternalType('array', $json);
$this->assertIsArray($json);
$this->assertNotEmpty($json);
$this->assertEquals(10, count($json));
foreach ($json as $result) {
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
$this->assertCalendarStructure($result);
}
}

View File

@@ -63,6 +63,7 @@ class TimesheetFixtures extends Fixture
public function setAllowEmptyDescriptions(bool $allowEmptyDescriptions)
{
$this->allowEmptyDescriptions = $allowEmptyDescriptions;
return $this;
}

View File

@@ -28,13 +28,13 @@ class ServiceInvoiceTest extends TestCase
$sut = new ServiceInvoice($repo);
$this->assertEmpty($sut->getCalculator());
$this->assertInternalType('array', $sut->getCalculator());
$this->assertIsArray($sut->getCalculator());
$this->assertEmpty($sut->getRenderer());
$this->assertInternalType('array', $sut->getRenderer());
$this->assertIsArray($sut->getRenderer());
$this->assertEmpty($sut->getNumberGenerator());
$this->assertInternalType('array', $sut->getNumberGenerator());
$this->assertIsArray($sut->getNumberGenerator());
$this->assertEmpty($sut->getDocuments());
$this->assertInternalType('array', $sut->getDocuments());
$this->assertIsArray($sut->getDocuments());
$this->assertNull($sut->getCalculatorByName('default'));
$this->assertNull($sut->getDocumentByName('default'));

View File

@@ -33,7 +33,7 @@ class InvoiceModelTest extends TestCase
$this->assertNull($sut->getQuery());
$this->assertNull($sut->getDueDate());
$this->assertEmpty($sut->getEntries());
$this->assertInternalType('array', $sut->getEntries());
$this->assertIsArray($sut->getEntries());
$this->assertInstanceOf(\DateTime::class, $sut->getInvoiceDate());
}

View File

@@ -23,7 +23,7 @@ class YearTest extends TestCase
$sut = new Year('1999');
$this->assertNull($sut->getMonth('01'));
$this->assertEmpty($sut->getMonths());
$this->assertInternalType('array', $sut->getMonths());
$this->assertIsArray($sut->getMonths());
$this->assertEquals('1999', $sut->getYear());
}

View File

@@ -36,7 +36,7 @@ class InvoiceDocumentRepositoryTest extends TestCase
{
$sut = new InvoiceDocumentRepository([]);
$this->assertEmpty($sut->findAll());
$this->assertInternalType('array', $sut->findAll());
$this->assertIsArray($sut->findAll());
$this->assertNull($sut->findByName('default'));
}

View File

@@ -45,7 +45,7 @@ class TimesheetRepositoryTest extends AbstractRepositoryTest
$query->setResultType(BaseQuery::RESULT_TYPE_OBJECTS);
$result = $repository->findByQuery($query);
$this->assertInternalType('array', $result);
$this->assertIsArray($result);
}
public function testStoppedEntriesCannotBeStoppedAgain()

View File

@@ -220,7 +220,7 @@ class ExtensionsTest extends TestCase
foreach ($icons as $icon) {
$result = $sut->icon($icon);
$this->assertNotEmpty($result, 'Problem with icon definition: ' . $icon);
$this->assertInternalType('string', $result);
$this->assertIsString($result);
}
// test fallback will be returned

View File

@@ -20,6 +20,8 @@ class DurationTest extends TestCase
public function testFormat()
{
$sut = new Duration();
$this->assertNull($sut->format(null));
$this->assertEquals('02:38', $sut->format(9494));
$this->assertEquals('02:38:14', $sut->format(9494, Duration::FORMAT_WITH_SECONDS));
}
@@ -73,7 +75,7 @@ class DurationTest extends TestCase
['13', Duration::FORMAT_COLON],
['13-13', Duration::FORMAT_COLON],
['13.13', Duration::FORMAT_COLON],
[1111, 1111, Duration::FORMAT_NATURAL],
[1111, Duration::FORMAT_NATURAL],
// invalid modes
[17, 'foo'],

View File

@@ -142,6 +142,7 @@ class LocaleSettingsTest extends TestCase
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Unknown locale given: xx
*/
public function testInvalidLocaleWithGivenLocale()
{
@@ -197,4 +198,16 @@ class LocaleSettingsTest extends TestCase
$this->assertEquals('YYYY-MM-DD HH:mm', $sut->getDateTimePickerFormat());
$this->assertEquals('DD.MM.YYYY HH:mm', $sut->getDateTimePickerFormat('de'));
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Unknown setting for locale en: date_time_picker
*/
public function testUnknownSetting()
{
$sut = $this->getSut('en', ['en' => [
'xxx' => 'dd.MM.yyyy HH:mm',
]]);
$sut->getDateTimePickerFormat('en');
}
}

View File

@@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase;
/**
* @covers \App\Utils\Markdown
* @covers \App\Utils\ParsedownExtension
*/
class MarkdownTest extends TestCase
{
@@ -51,6 +52,26 @@ sdfsdf [asdfasdf](#test-1) asdfasdf
# test
aasdfasdf
EOT;
$this->assertEquals($html, $sut->toHtml($markdown));
}
public function testDuplicateIds()
{
$sut = new Markdown();
$html = <<<'EOT'
<h1 id="test">test</h1>
<h2 id="test-1">test</h2>
<h3 id="test-2">test</h3>
<h1 id="test-3">test</h1>
EOT;
$markdown = <<<EOT
# test
## test
### test
# test
EOT;
$this->assertEquals($html, $sut->toHtml($markdown));
}

View File

@@ -1,5 +1,18 @@
# Configurations
This is an introduction into the configuration options and files, which are used by Kimai and an explanantion on how to change them.
Specific configurations are explained in the detailed feature docs:
- [Timesheet](timesheet.md)
- [Permissions](permissions.md)
- [Invoice](invoices.md)
- [Calendar](calendar.md)
- [Customer](customer.md)
- [Emails](emails.md)
- [Dashboard widgets](dashboard.md)
- [Theme](theme.md)
## Environment specific settings (.env)
The most basic settings, which need always be adjusted are stored in the `.env` file:
@@ -19,20 +32,12 @@ Configuration of Kimai is spread in all files in the `config/`directory but main
- `config/packages/kimai.yaml` - Kimai specific settings
- `config/packages/admin_lte.yaml` - Kimai base theme
- `config/packages/fos_user.yaml` - user management and email settings
- `config/packages/local.yaml` - your local configuration settings
- `config/packages/local.yaml` - your configuration settings (file needs to be created by yourself)
There are several other configurations that could potentially be interesting for you in [config/packages/*.yaml](../../config/packages/).
If you want to adjust a setting from any of these files, use `local.yaml` (see below).
#### Other topics
- [Theme settings](theme.md) - in `kimai.yaml` and `admin_lte.yaml`
- [Email configuration](emails.md) - in `swiftmailer.yaml`
- [Dashboard widgets](dashboard.md) - in `kimai.yaml`
- [Calendar](calendar.md) - in `kimai.yaml`
- [Invoices](invoices.md) - in `kimai.yaml`
## Overwriting local configs (local.yaml)
You should NOT edit the file `config/packages/kimai.yaml` directly, as it contains default settings and will be overwritten during an update.
@@ -71,202 +76,3 @@ bin/console cache:warmup --env=prod
Depending on your setup it might be necessary to execute these commands as webserver user,
please read the [UPGRADING guide](../../UPGRADING.md) for more details.
## Security
Kimai uses the FOSUserBundle for security related tasks like user management. Its configuration can be found in [fos_user.yaml](../../config/packages/fos_user.yaml).
### User management emails (fos_user.yaml)
Read more about [email configuration](emails.md).
### Remember me login (security.yaml)
The default period for the `Remember me` option can be changed in the config file [security.yaml](../../config/packages/security.yaml).
### User registration
If you want your new users to use [email](emails.md) based activation add this to your `local.yaml`:
```yaml
fos_user:
registration:
confirmation:
enabled: true
```
#### Disable user registration
If you want to disable the user registration, add this your `local.yaml`:
```yaml
kimai:
user:
registration: false
```
If you only want to hide the link from the login form but keep the functionality, add this your `local.yaml`:
```yaml
admin_lte:
routes:
adminlte_registration: ~
```
### Password reset
If you want to configure the behaviour (like the allowed time between multiple retries) then configure the settings:
- in `config/packages/fos_user.yaml` the key below `fos_user.registration.resetting` (see [documentation](https://symfony.com/doc/current/bundles/FOSUserBundle/configuration_reference.html))
- the values `retry_ttl` and `token_ttl` are configured in seconds (7220 = 2 hours)
#### Disable password reset
If you want to disable the password reset, add this your `local.yaml`:
```yaml
kimai:
user:
password_reset: false
```
If you only want to hide the link from the login form but keep the functionality, add this your `local.yaml`:
```yaml
admin_lte:
routes:
adminlte_password_reset: ~
```
## Timesheets (kimai.yaml)
### Limit active entries
To limit the amount of active entries each user can have, the configuration `active_entries` can be changed:
```yaml
kimai:
timesheet:
active_entries:
soft_limit: 1
hard_limit: 3
```
The `soft_limit` is used as theme setting (formerly "kimai.theme.active_warning") to display a warning if the user has at least X active recordings.
The `hard_limit` is used to detect how many active records are allowed per user (by default 3 active time-records are allowed).
If `hard_limit` is 1, the active record is automatically stopped when a new one is started.
When `hard_limit` is greater than 1 and as soon as the limit is reached, the user has to manually stop at least one active
entry (an error message is shown, indicating why it is not possible to start another one).
### Descriptions with Markdown
The description for every timesheet entry can be formatted in two different ways, configured with the `markdown_content` setting.
- `false` - simple newlines in the description box will be displayed in the frontend as well (default)
- `true` - description will be rendered with a markdown engine, supporting simple lists and other HTML content
Allowing Markdown in timesheet descriptions is beautiful, but also could be a [security risk](https://github.com/erusev/parsedown/blob/master/README.md#security).
Kimai will only apply the markdown in the user timesheet and not in the admin section as additional security measure.
### Duration only
Kimai supports two modes for displaying and recording timesheet entries:
- `begin` and `end` time (default)
- `date` and `duration` (the so called `duration_only` mode)
When activating the `duration_only` mode all timesheet tables will only display the `date` and `duration` of all records.
In addition, the "edit timesheet" forms will be changed and instead of displaying the `end` date you will see a field for `duration`.
The `start` date is only visible in these forms when editing an active or starting a new record.
You can activate the `duration_only` mode by switching the configuration key `kimai.timesheet.duration_only` to `true` in the file [kimai.yaml](../../config/packages/kimai.yaml).
For supported formats while entering the `duration` please see the [timesheet chapter](timesheet.md)
### Rounding of begin, end and duration for timesheet records
Rounding rules are used to round the begin & end dates and the duration for timesheet records.
1. You can define as many rules as you want ("default" is only an example)
2. Every matching rule will be applied, so be careful with overlapping rules
3. The end_date of timesheet records will be used to match the day (think about entries which are recorded overnight)
4. If you set one of "begin", "end", "duration" to 0 no rounding will be applied for that field and the exact time (including seconds) is used for calculation
5. The values of the rules are minutes (not the minute of an hour), so 5 for "begin" means we round down to the previous multiple of five
6. You can define different rules for different days of the week
7. "begin" will always be rounded to the floor (down) and "end" & "duration" to the ceiling (up)
8. Rounding rules will be applied on stopped timesheet records only, so you might see an un-rounded value for the start time and duration until you stop the record
You can configure your `rounding` rules by changing the configuration file [kimai.yaml](../../config/packages/kimai.yaml).
#### Examples
A simple example to always charge at least 1 hour for weekend work (even if you only worked for 5 minutes) could look like this:
```yaml
kimai:
timesheet:
rounding:
weekend:
days: ['saturday','sunday']
begin: 1
end: 1
duration: 60
```
A rule which is often used is to round up to a mulitple of 10:
```yaml
kimai:
timesheet:
rounding:
workdays:
days: ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
begin: 10
end: 10
duration: 0
```
### Hourly rates for timesheet records
If you want to apply different hourly rates multiplication `factor` for specific weekdays, you can use this `rates` configuration.
1. You can define as many rules as you want ("workdays" and "weekend" are only examples)
2. Every matching rule will be applied, so be careful with overlapping rules
3. The end_date of timesheet records will be used to match the day (think about entries which are recorded overnight)
4. "days" is an array of weekdays, where the days need to be written in english and in lowercase
5. "factor" will be used as multiplier for the applied hourly rate
6. Rate rules will be applied on stopped timesheet records only, as it can't be calculated before
7. There is no default rule active, by default the users hourly-rate is used for calculation
You can configure the `hourly_rate` rules by changing the configuration file [kimai.yaml](../../config/packages/kimai.yaml).
#### Examples
1. The "workdays" rule will use the default "hourly rate" for each timesheet entry recorded between "monday" to "friday" as a multiplication with 1 will not change the result
2. The "weekend" rule will add 50% to each timesheet entry that will be recorded on "saturdays" or "sundays"
```yaml
kimai:
timesheet:
rates:
workdays:
days: ['monday','tuesday','wednesday','thursday','friday']
factor: 1
weekend:
days: ['saturday','sunday']
factor: 1.5
```
## Forms (kimai.yaml)
You can set some defaults for various forms within Kimai, to easify the creation process.
### Customer creation
Define the default values for a customer like this:
```yaml
kimai:
defaults:
customer:
timezone: Europe/London
country: GB
currency: GBP
```

17
var/docs/customer.md Normal file
View File

@@ -0,0 +1,17 @@
# Customer
Customers in Kimai are used to manage project and activities, which are then used for time-records.
It is very common to have a _customer_ for your own company, to track times for administration and other internal work.
## Creating customer
Define the default values for a customer like this:
```yaml
kimai:
defaults:
customer:
timezone: Europe/London
country: GB
currency: GBP
```

View File

@@ -2,10 +2,22 @@
## I have a problem
Please open a new issue at [GitHub](https://github.com/kevinpapst/kimai2/issues/).
Add the last entries from your logfile at `var/log/prod.log`.
Please check your logfile at `var/log/prod.log`. Many problems reveal themselves after checking it.
## I have only FTP available ...
If that doesn't help, open a new issue at [GitHub](https://github.com/kevinpapst/kimai2/issues/) and we try to find a solution.
## Changed configs/templates do not load
Kimai is built on top of Symfony, a framework that optimizes its speed by caching most files.
Therefor, if you are running Kimai in `production`, you have to clear the cache before changes will show up:
```bash
bin/console cache:clear
```
See also the [configurations docs](configurations.md).
## I have only FTP available
So you want to install Kimai v2 but have no SSH access to your server?
There is a workaround available, read the additional [installation instructions](installation.md).
@@ -26,22 +38,17 @@ used by executing `mysql --version` or by checking the server information e.g. w
There is a [discussion in the issue tracker](https://github.com/kevinpapst/kimai2/issues/191) about this topic.
There are two solution for this:
- Update your MariaDB server to at least 10.2.7
- Switch to SQLite (that can be changed in your `.env` file)
Further readings:
- [MariaDB - JSON support was added with 10.2.7](https://mariadb.com/kb/en/library/json-data-type/)
- [Using JSON fields with Doctrine ORM on PostgreSQL & MySQL](https://symfony.fi/entry/using-json-fields-with-doctrine-orm-on-postgresql-mysql)
## Why is SQLite not recommended for production usage
## SQLite not recommended for production usage
SQLite is a great database engine for testing, but when it comes to production usage it fails due to several reasons:
- It does not support ALTER TABLE commands and makes update procedures very clunky and problematic/errorsome (we still try to support updates, but they are heavy on large databases)
- It does not support FOREIGN KEY constraints out of the box, which can lead to critical bugs when deleting activities/projects/customers
- It does not support ALTER TABLE commands and makes update procedures very clunky and problematic (we still try to support updates, but they are heavy on large databases)
- It does not support FOREIGN KEY constraints [out of the box](https://www.sqlite.org/foreignkeys.html#fk_enable), which can lead to critical bugs when deleting users/activities/projects/customers
## Dotenv::populate() must be an instance of Symfony\\Component\\Dotenv\\void

View File

@@ -17,7 +17,7 @@ You need to install Git and [Composer](https://getcomposer.org/doc/00-intro.md)
First clone this repo:
```bash
git clone https://github.com/kevinpapst/kimai2.git
git clone -b 0.8 --depth 1 https://github.com/kevinpapst/kimai2.git
cd kimai2/
```

View File

@@ -7,7 +7,8 @@ Internal documentation for project maintainers
- Prepare a GitHub release-draft
- Change .github_changelog_generator config accordingly to new release tag (increase future release)
- Change version constants in `src/Constants.php`
- Adjust the file `UPGRADING.md` with version specific information
- Adjust the file `UPGRADING.md` with version specific information
- Change version string in git command in `UPGRADING.md` and `var/docs/installation.md`
- Create CHANGELOG.md with [github-changelog-generator](https://github.com/github-changelog-generator/github-changelog-generator]) by running `github_changelog_generator kevinpapst/kimai2`
- Edit the release-draft and add the "Full changelog" link + everything from CHANGELOG.md related to the new version
- Push a release branch and merge it as last PR into master

View File

@@ -11,8 +11,6 @@ You can start new timesheet records like so:
- Click the **redo** button from one of the activities in your timesheet
- Start a completely new activity, by clicking the big **play** button in the toolbar
The same goes for running time-records: top them with one-click from the timesheet or from the "running entries" dropdown.
## Stopping records
You can stop timesheet records like so:
@@ -22,7 +20,24 @@ You can stop timesheet records like so:
## Duration only mode
When the `duration_only` mode is activated, you will only see the `date` and `duration` fields (see [configurations chapter](configurations.md)).
Kimai supports two modes for displaying and recording timesheet entries:
- `begin` and `end` time (default)
- `date` and `duration` (the so called `duration_only` mode)
When activating the `duration_only` mode all timesheet tables will only display the `date` and `duration` of all records.
In addition, the "edit timesheet" forms will be changed and instead of displaying the `end` date you will see a field for `duration`.
The `start` date is only visible in these forms when editing an active or starting a new record.
You can activate the `duration_only` mode by switching the configuration key `kimai.timesheet.duration_only` to `true` in your `local.yaml`:
```yaml
kimai:
timesheet:
duration_only: true
```
### Duration format
The `duration` field supports entering data in the following formats:
@@ -34,6 +49,78 @@ The `duration` field supports entering data in the following formats:
Please note: if time rounding is activated (which is the default behaviour), then your entered seconds might be removed after submitting the form.
## Limit active entries
To limit the amount of active entries each user can have, the configuration `active_entries` can be changed:
```yaml
kimai:
timesheet:
active_entries:
soft_limit: 1
hard_limit: 3
```
The `soft_limit` is used as theme setting (formerly "kimai.theme.active_warning") to display a warning if the user has at least X active recordings.
The `hard_limit` is used to detect how many active records are allowed per user (by default 3 active time-records are allowed).
If `hard_limit` is 1, the active record is automatically stopped when a new one is started.
When `hard_limit` is greater than 1 and as soon as the limit is reached, the user has to manually stop at least one active
entry (an error message is shown, indicating why it is not possible to start another one).
## Descriptions with Markdown
The description for every timesheet entry can be formatted in two different ways, configured with the `markdown_content` setting.
- `false` - simple newlines in the description box will be displayed in the frontend as well (default)
- `true` - description will be rendered with a markdown engine, supporting simple lists and other HTML content
Allowing Markdown in timesheet descriptions is beautiful, but also could be a [security risk](https://github.com/erusev/parsedown/blob/master/README.md#security).
Kimai will only apply the markdown in the user timesheet and not in the admin section as additional security measure.
## Rounding of begin, end and duration for timesheet records
Rounding rules are used to round the begin & end dates and the duration for timesheet records.
1. You can define as many rules as you want ("default" is only an example)
2. Every matching rule will be applied, so be careful with overlapping rules
3. The end_date of timesheet records will be used to match the day (think about entries which are recorded overnight)
4. If you set one of "begin", "end", "duration" to 0 no rounding will be applied for that field and the exact time (including seconds) is used for calculation
5. The values of the rules are minutes (not the minute of an hour), so 5 for "begin" means we round down to the previous multiple of five
6. You can define different rules for different days of the week
7. "begin" will always be rounded to the floor (down) and "end" & "duration" to the ceiling (up)
8. Rounding rules will be applied on stopped timesheet records only, so you might see an un-rounded value for the start time and duration until you stop the record
You can configure your `rounding` rules by changing the configuration file [kimai.yaml](../../config/packages/kimai.yaml).
### Examples
A simple example to always charge at least 1 hour for weekend work (even if you only worked for 5 minutes) could look like this:
```yaml
kimai:
timesheet:
rounding:
weekend:
days: ['saturday','sunday']
begin: 1
end: 1
duration: 60
```
A rule which is often used is to round up to a mulitple of 10:
```yaml
kimai:
timesheet:
rounding:
workdays:
days: ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
begin: 10
end: 10
duration: 0
```
## Rate calculation
There are two rate types:
@@ -63,5 +150,35 @@ The calculation is based on the following formula:
- __Fixed rate__: `$fixedRate`
- __Hourly rate__: `$hourlyRate * ($durationInSeconds / 3600) * $factor`
Please see also the configuration chapter about [hourly rates for timesheet records](configurations.md) to see how you
can apply configurable multiplying factors based on day and time.
Please see below to see how you can apply configurable multiplying factors based on day and time.
### Rate multiplier for specific weekdays
If you want to apply different hourly rates multiplication `factor` for specific weekdays, you can use this `rates` configuration.
1. You can define as many rules as you want ("workdays" and "weekend" are only examples)
2. Every matching rule will be applied, so be careful with overlapping rules
3. The end_date of timesheet records will be used to match the day (think about entries which are recorded overnight)
4. "days" is an array of weekdays, where the days need to be written in english and in lowercase
5. "factor" will be used as multiplier for the applied hourly rate
6. Rate rules will be applied on stopped timesheet records only, as it can't be calculated before
7. There is no default rule active, by default the users hourly-rate is used for calculation
You can configure the `hourly_rate` rules by changing the configuration file [kimai.yaml](../../config/packages/kimai.yaml).
#### Examples
1. The "workdays" rule will use the default "hourly rate" for each timesheet entry recorded between "monday" to "friday" as a multiplication with 1 will not change the result
2. The "weekend" rule will add 50% to each timesheet entry that will be recorded on "saturdays" or "sundays"
```yaml
kimai:
timesheet:
rates:
workdays:
days: ['monday','tuesday','wednesday','thursday','friday']
factor: 1
weekend:
days: ['saturday','sunday']
factor: 1.5
```

View File

@@ -16,7 +16,8 @@ personal computer instead of a server. Read the [installation docu](installation
Change into your Kimai 2 installation directory, then fetch the latest code and install all dependencies:
```bash
git pull origin master
git fetch --tags
git checkout 0.8
sudo -u www-data composer install --no-dev --optimize-autoloader
```

View File

@@ -21,6 +21,9 @@ The permission system is configurable through a configuration file. You can find
- User can login with username or email
- If you activate the `Remember me` option, you can use use the most common functions within the next days without a new login
Kimai uses the FOSUserBundle for security related tasks like user management.
Its configuration can be found in [fos_user.yaml](../../config/packages/fos_user.yaml).
### Remember me login
If you have chosen to login with the `Remember me` option, your login will be extended to one week (default value).
@@ -34,13 +37,39 @@ If you are an administrator, you will see all your allowed options in the menu,
form when you try to access them. This is a security feature to prevent abuse in case you forgot to logout in public
environments.
Read the [configurations chapter](configurations.md) if you want to change the value.
The default period for the `Remember me` option can be changed in the config file [security.yaml](../../config/packages/security.yaml).
## User registration
User registration with instant approval is activated by default, so users can register and will be able to login and start time-tracking instantly.
Read the [configurations chapter](configurations.md) if you want to disable the registration or enable email verification.
If you want to disable the registration or enable email verification, read further below under _Configurations_.
### Email activation
If you want your new users to use [email](emails.md) based activation add this to your `local.yaml`:
```yaml
fos_user:
registration:
confirmation:
enabled: true
```
### Disable user registration
If you want to disable the user registration, add this your `local.yaml`:
```yaml
kimai:
user:
registration: false
```
If you only want to hide the link from the login form but keep the functionality, add this your `local.yaml`:
```yaml
admin_lte:
routes:
adminlte_registration: ~
```
## Password reset
@@ -56,4 +85,19 @@ If you want to configure the behaviour (like the allowed time between multiple r
- in `config/packages/fos_user.yaml` the key below `fos_user.registration.resetting` (see [documentation](https://symfony.com/doc/current/bundles/FOSUserBundle/configuration_reference.html))
- the values `retry_ttl` and `token_ttl` are configured in seconds (7220 = 2 hours)
Read the [configurations chapter](configurations.md) if you want to reload the changed configuration files.
### Disable password reset
If you want to disable the password reset, add this your `local.yaml`:
```yaml
kimai:
user:
password_reset: false
```
If you only want to hide the link from the login form but keep the functionality, add this your `local.yaml`:
```yaml
admin_lte:
routes:
adminlte_password_reset: ~
```