Merge branch 'release/5.6.0-alpha.2' into main

This commit is contained in:
James Cole
2021-08-10 19:54:31 +02:00
380 changed files with 14202 additions and 6923 deletions

View File

@@ -260,12 +260,6 @@ DISABLE_CSP_HEADER=false
TRACKER_SITE_ID=
TRACKER_URL=
#
# Firefly III can collect telemetry on how you use Firefly III. This is opt-in.
# In order to allow this, change the following variable to true.
# To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry
SEND_TELEMETRY=false
# You can fine tune the start-up of a Docker container by editing these environment variables.
# Use this at your own risk. Disabling certain checks and features may result in lost of inconsistent data.
# However if you know what you're doing you can significantly speed up container start times.

View File

@@ -261,12 +261,6 @@ DISABLE_CSP_HEADER=false
TRACKER_SITE_ID=
TRACKER_URL=
#
# Firefly III can collect telemetry on how you use Firefly III. This is opt-in.
# In order to allow this, change the following variable to true.
# To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry
SEND_TELEMETRY=false
# You can fine tune the start-up of a Docker container by editing these environment variables.
# Use this at your own risk. Disabling certain checks and features may result in lost of inconsistent data.
# However if you know what you're doing you can significantly speed up container start times.

View File

@@ -38,12 +38,6 @@ TRUSTED_PROXIES=
# Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself.
# A rotating log option is 'daily', creates 5 files that (surprise) rotate.
# Default setting 'stack' will log to 'daily' and to 'stdout' at the same time.
# - Docker + versions <= 4.8.1.8 and before: use "stdout"
# - Docker + versions > 4.8.1.8 : use "docker_out"
# - Docker + versions >= 5.1.1 : use "stack"
# - For everything else (als not Docker) : use 'stack'
LOG_CHANNEL=stack
# Log level. You can set this from least severe to most severe:
@@ -174,23 +168,21 @@ MAP_DEFAULT_ZOOM=6
# - 'remote_user_guard' for Authelia etc
# Read more about these settings in the documentation.
# https://docs.firefly-iii.org/advanced-installation/authentication
#
# Set to 'ldap' to enable LDAP
#
AUTHENTICATION_GUARD=web
#
# LDAP connection settings:
#
LDAP_HOST=ldap.yourserver.com
LDAP_USERNAME="uid=X,ou=,o=,dc=something,dc=com"
LDAP_PASSWORD=super_secret
LDAP_PORT=389
LDAP_BASE_DN="o=something,dc=site,dc=com"
LDAP_TIMEOUT=5
LDAP_SSL=false
LDAP_TLS=false
LDAP_BASE_DN="o=something,dc=site,dc=com"
LDAP_USERNAME="uid=X,ou=,o=,dc=something,dc=com"
LDAP_PASSWORD=super_secret
LDAP_AUTH_FIELD=uid
#
@@ -199,7 +191,6 @@ LDAP_AUTH_FIELD=uid
AUTHENTICATION_GUARD_HEADER=REMOTE_USER
AUTHENTICATION_GUARD_EMAIL=
#
# Extra authentication settings
#

BIN
.github/assets/img/imac-complete.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 KiB

BIN
.github/assets/img/ipad-complete.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 921 KiB

BIN
.github/assets/img/iphone-complete.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

BIN
.github/assets/img/logo-small.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
@@ -91,7 +92,7 @@ abstract class Controller extends BaseController
if (null !== $date) {
try {
$obj = Carbon::parse($date);
} catch (InvalidDateException $e) {
} catch (InvalidDateException|InvalidFormatException $e) {
// don't care
Log::error(sprintf('Invalid date exception in API controller: %s', $e->getMessage()));
}

View File

@@ -1,4 +1,25 @@
<?php
/*
* AccountController.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Data\Bulk;
@@ -12,11 +33,16 @@ use Illuminate\Http\JsonResponse;
/**
* Class AccountController
*
* @deprecated
*/
class AccountController extends Controller
{
private AccountRepositoryInterface $repository;
/**
*
*/
public function __construct()
{
parent::__construct();
@@ -37,8 +63,8 @@ class AccountController extends Controller
*/
public function moveTransactions(MoveTransactionsRequest $request): JsonResponse
{
$accountIds = $request->getAll();
$original = $this->repository->find($accountIds['original_account']);
$accountIds = $request->getAll();
$original = $this->repository->find($accountIds['original_account']);
$destination = $this->repository->find($accountIds['destination_account']);
/** @var AccountDestroyService $service */

View File

@@ -0,0 +1,97 @@
<?php
/*
* TransactionController.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Data\Bulk;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\Bulk\TransactionRequest;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
use Illuminate\Http\JsonResponse;
/**
* Class TransactionController
*
* Endpoint to update transactions by submitting
* (optional) a "where" clause and an "update"
* clause.
*
* Because this is a security nightmare waiting to happen validation
* is pretty strict.
*/
class TransactionController extends Controller
{
private AccountRepositoryInterface $repository;
/**
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser(auth()->user());
return $next($request);
}
);
}
/**
* @param TransactionRequest $request
*
* @return JsonResponse
*/
public function update(TransactionRequest $request): JsonResponse
{
$query = $request->getAll();
$params = $query['query'];
// this deserves better code, but for now a loop of basic if-statements
// to respond to what is in the $query.
// this is OK because only one thing can be in the query at the moment.
if ($this->updatesTransactionAccount($params)) {
$original = $this->repository->find((int)$params['where']['source_account_id']);
$destination = $this->repository->find((int)$params['update']['destination_account_id']);
/** @var AccountDestroyService $service */
$service = app(AccountDestroyService::class);
$service->moveTransactions($original, $destination);
}
return response()->json([], 204);
}
/**
* @param array $params
*
* @return bool
*/
private function updatesTransactionAccount(array $params): bool
{
return array_key_exists('source_account_id', $params['where']) && array_key_exists('destination_account_id', $params['update']);
}
}

View File

@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
/*
* AccountController.php
* ExportController.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Data\Export;
use FireflyIII\Api\V1\Controllers\Controller;

View File

@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
/*
* PeriodController.php
* BillController.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Insight\Expense;
use FireflyIII\Api\V1\Controllers\Controller;

View File

@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
/*
* PeriodController.php
* TagController.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Insight\Expense;
use FireflyIII\Api\V1\Controllers\Controller;

View File

@@ -38,7 +38,6 @@ use Illuminate\Http\JsonResponse;
*
* Shows income information grouped or limited by date.
* Ie. all income grouped by account + currency.
* See reference nr. 75
*/
class AccountController extends Controller
{
@@ -74,9 +73,6 @@ class AccountController extends Controller
}
/**
* See reference nr. 76
* See reference nr. 77
*
* @param GenericRequest $request
*
* @return JsonResponse
@@ -104,8 +100,6 @@ class AccountController extends Controller
}
/**
* See reference nr. 78
*
* @param GenericRequest $request
*
* @return JsonResponse

View File

@@ -35,7 +35,6 @@ use Illuminate\Support\Collection;
/**
* Class CategoryController
* See reference nr. 79
*/
class CategoryController extends Controller
{

View File

@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
/*
* PeriodController.php
* TagController.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Insight\Income;
use FireflyIII\Api\V1\Controllers\Controller;

View File

@@ -58,8 +58,6 @@ class AccountController extends Controller
}
/**
* See reference nr. 80
* See reference nr. 81
*
* @param GenericRequest $request
*

View File

@@ -39,7 +39,6 @@ class TagController extends Controller
/**
* TagController constructor.
* See reference nr. 82
*/
public function __construct()
{

View File

@@ -26,7 +26,6 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionLink;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\TransactionLink\UpdateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionJournalLink;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
@@ -71,8 +70,6 @@ class UpdateController extends Controller
* @param TransactionJournalLink $journalLink
*
* @return JsonResponse
*
* See reference nr. 84
*/
public function update(UpdateRequest $request, TransactionJournalLink $journalLink): JsonResponse
{

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\User;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\User\PreferenceStoreRequest;
use FireflyIII\Api\V1\Requests\User\PreferenceUpdateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Preference;
use FireflyIII\Transformers\PreferenceTransformer;
use Illuminate\Http\JsonResponse;
@@ -47,13 +48,12 @@ class PreferencesController extends Controller
* List all of them.
*
* @return JsonResponse
* @throws \FireflyIII\Exceptions\FireflyException
* @throws FireflyException
* @codeCoverageIgnore
*/
public function index(): JsonResponse
{
// See reference nr. 83
$collection = auth()->user()->preferences()->get();
$collection = app('preferences')->all();
$manager = $this->getManager();
$count = $collection->count();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@@ -119,7 +119,7 @@ class PreferencesController extends Controller
* @param Preference $preference
*
* @return JsonResponse
* @throws \FireflyIII\Exceptions\FireflyException
* @throws FireflyException
*/
public function update(PreferenceUpdateRequest $request, Preference $preference): JsonResponse
{

View File

@@ -1,4 +1,25 @@
<?php
/*
* MoveTransactionsRequest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Data\Bulk;

View File

@@ -0,0 +1,86 @@
<?php
/*
* TransactionRequest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Data\Bulk;
use FireflyIII\Enums\ClauseType;
use FireflyIII\Rules\IsValidBulkClause;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\Api\Data\Bulk\ValidatesBulkTransactionQuery;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
use JsonException;
use Log;
/**
* Class TransactionRequest
*/
class TransactionRequest extends FormRequest
{
use ChecksLogin, ConvertsDataTypes, ValidatesBulkTransactionQuery;
/**
* @return array
*/
public function getAll(): array
{
$data = [];
try {
$data = [
'query' => json_decode($this->get('query'), true, 8, JSON_THROW_ON_ERROR),
];
} catch (JsonException $e) {
// dont really care. the validation should catch invalid json.
Log::error($e->getMessage());
}
return $data;
}
/**
* @return string[]
*/
public function rules(): array
{
return [
'query' => ['required', 'min:1', 'max:255', 'json', new IsValidBulkClause(ClauseType::TRANSACTION)],
];
}
/**
* @param Validator $validator
*
* @return void
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator) {
// validate transaction query data.
$this->validateTransactionQuery($validator);
}
);
}
}

View File

@@ -55,6 +55,8 @@ class StoreRequest extends FormRequest
'currency_id' => ['currency_id', 'integer'],
'currency_code' => ['currency_code', 'string'],
'date' => ['date', 'date'],
'end_date' => ['end_date', 'date'],
'extension_date' => ['extension_date', 'date'],
'repeat_freq' => ['repeat_freq', 'string'],
'skip' => ['skip', 'integer'],
'active' => ['active', 'boolean'],
@@ -75,16 +77,18 @@ class StoreRequest extends FormRequest
public function rules(): array
{
return [
'name' => 'between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'numeric|gt:0',
'amount_max' => 'numeric|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'date' => 'date',
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
'skip' => 'between:0,31',
'active' => [new IsBoolean],
'notes' => 'between:1,65536',
'name' => 'between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'numeric|gt:0|required',
'amount_max' => 'numeric|gt:0|required',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'date' => 'date|required',
'end_date' => 'date|after:date',
'extension_date' => 'date|after:date',
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly|required',
'skip' => 'between:0,31',
'active' => [new IsBoolean],
'notes' => 'between:1,65536',
];
}

View File

@@ -53,6 +53,8 @@ class UpdateRequest extends FormRequest
'currency_id' => ['currency_id', 'integer'],
'currency_code' => ['currency_code', 'string'],
'date' => ['date', 'date'],
'end_date' => ['end_date', 'date'],
'extension_date' => ['extension_date', 'date'],
'repeat_freq' => ['repeat_freq', 'string'],
'skip' => ['skip', 'integer'],
'active' => ['active', 'boolean'],
@@ -75,16 +77,18 @@ class UpdateRequest extends FormRequest
$bill = $this->route()->parameter('bill');
return [
'name' => sprintf('between:1,255|uniqueObjectForUser:bills,name,%d', $bill->id),
'amount_min' => 'numeric|gt:0',
'amount_max' => 'numeric|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'date' => 'date',
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
'skip' => 'between:0,31',
'active' => [new IsBoolean],
'notes' => 'between:1,65536',
'name' => sprintf('between:1,255|uniqueObjectForUser:bills,name,%d', $bill->id),
'amount_min' => 'numeric|gt:0',
'amount_max' => 'numeric|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'date' => 'date',
'end_date' => 'date|after:date',
'extension_date' => 'date|after:date',
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
'skip' => 'between:0,31',
'active' => [new IsBoolean],
'notes' => 'between:1,65536',
];
}

View File

@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
/*
* PreferenceStoreRequest.php
* PreferenceUpdateRequest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\User;
use FireflyIII\Support\Request\ChecksLogin;

View File

@@ -1,4 +1,25 @@
<?php
/*
* FixPostgresSequences.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
@@ -88,7 +109,6 @@ class FixPostgresSequences extends Command
'rules',
'tag_transaction_journal',
'tags',
'telemetry',
'transaction_currencies',
'transaction_groups',
'transaction_journals',

View File

@@ -1,4 +1,25 @@
<?php
/*
* UpgradeLiabilities.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Upgrade;

View File

@@ -1,4 +1,25 @@
<?php
/*
* VerifySecurityAlerts.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;

View File

@@ -1,7 +1,8 @@
<?php
/*
* UpdatedTransactionLink.php
* Copyright (c) 2020 james@firefly-iii.org
* ClauseType.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -21,27 +22,14 @@
declare(strict_types=1);
namespace FireflyIII\Events;
use FireflyIII\Models\TransactionJournalLink;
use Illuminate\Queue\SerializesModels;
namespace FireflyIII\Enums;
/**
* Class UpdatedTransactionLink
* See reference nr. 86
* Class ClauseType
*/
class UpdatedTransactionLink extends Event
class ClauseType
{
use SerializesModels;
private TransactionJournalLink $link;
/**
* DestroyedTransactionLink constructor.
*
* @param TransactionJournalLink $link
*/
public function __construct(TransactionJournalLink $link)
{
$this->link = $link;
}
public const TRANSACTION = 'transaction';
public const WHERE = 'where';
public const UPDATE = 'update';
}

View File

@@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/*
* StoredAccount.php
* Copyright (c) 2021 james@firefly-iii.org
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Events;
use FireflyIII\Models\Account;

View File

@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
/*
* StoredAccount.php
* UpdatedAccount.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -20,6 +20,9 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Events;
use FireflyIII\Models\Account;

View File

@@ -136,7 +136,6 @@ class Handler extends ExceptionHandler
*/
public function report(Throwable $e)
{
// do email the user (no telemetry)
$doMailError = config('firefly.send_error_message');
if ($this->shouldntReportLocal($e) || !$doMailError) {
parent::report($e);

View File

@@ -67,6 +67,8 @@ class BillFactory
'transaction_currency_id' => $currency->id,
'amount_max' => $data['amount_max'],
'date' => $data['date'],
'end_date' => $data['end_date'] ?? null,
'extension_date' => $data['extension_date'] ?? null,
'repeat_freq' => $data['repeat_freq'],
'skip' => $skip,
'automatch' => true,

View File

@@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/*
* WebhookMessageGenerator.php
* Copyright (c) 2020 james@firefly-iii.org
* StandardMessageGenerator.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Generator\Webhook;
use FireflyIII\Exceptions\FireflyException;

View File

@@ -0,0 +1,57 @@
<?php
/*
* LDAPEventHandler.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\User;
use LdapRecord\Laravel\Events\Import\Imported;
use Log;
/**
* Class LDAPEventHandler
*/
class LDAPEventHandler
{
/**
* @param Imported $event
*/
public function importedUser(Imported $event)
{
Log::debug(sprintf('Now in %s', __METHOD__));
/** @var User $user */
$user = $event->eloquent;
$alternative = User::where('email', $user->email)->where('id', '!=', $user->id)->first();
if (null !== $alternative) {
Log::debug(sprintf('User #%d is created but user #%d already exists.', $user->id, $alternative->id));
$alternative->objectguid = $user->objectguid;
$alternative->domain = $user->domain;
$alternative->save();
$user->delete();
auth()->logout();
}
}
}

View File

@@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/*
* StoredAccountEventHandler.php
* Copyright (c) 2021 james@firefly-iii.org
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\StoredAccount;

View File

@@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/*
* UpdatedAccountEventHandler.php
* Copyright (c) 2021 james@firefly-iii.org
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Events;

View File

@@ -29,6 +29,7 @@ use FireflyIII\Events\DetectedNewIPAddress;
use FireflyIII\Events\RegisteredUser;
use FireflyIII\Events\RequestedNewPassword;
use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Mail\ConfirmEmailChangeMail;
use FireflyIII\Mail\NewIPAddressWarningMail;
use FireflyIII\Mail\RegisteredUser as RegisteredUserMail;
@@ -190,6 +191,7 @@ class UserEventHandler
} catch (Exception $e) { // @phpstan-ignore-line
Log::error($e->getMessage());
}
return true;
}
@@ -216,6 +218,7 @@ class UserEventHandler
} catch (Exception $e) { // @phpstan-ignore-line
Log::error($e->getMessage());
}
return true;
}
@@ -241,6 +244,7 @@ class UserEventHandler
} catch (Exception $e) { // @phpstan-ignore-line
Log::error($e->getMessage());
}
return true;
}
@@ -283,6 +287,7 @@ class UserEventHandler
/**
* @param Login $event
*
* @throws \FireflyIII\Exceptions\FireflyException
*/
public function storeUserIPAddress(Login $event): void
@@ -290,9 +295,16 @@ class UserEventHandler
/** @var User $user */
$user = $event->user;
/** @var array $preference */
$preference = app('preferences')->getForUser($user, 'login_ip_history', [])->data;
$inArray = false;
$ip = request()->ip();
try {
$preference = app('preferences')->getForUser($user, 'login_ip_history', [])->data;
} catch (FireflyException $e) {
// don't care.
Log::error($e->getMessage());
return;
}
$inArray = false;
$ip = request()->ip();
Log::debug(sprintf('User logging in from IP address %s', $ip));
// update array if in array

View File

@@ -95,7 +95,7 @@ class Help implements HelpInterface
if ('' !== $content) {
Log::debug('Content is longer than zero. Expect something.');
$converter = new CommonMarkConverter();
$content = $converter->convertToHtml($content);
$content = (string) $converter->convertToHtml($content);
}
return $content;

View File

@@ -23,8 +23,11 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Webhook;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\WebhookMessage;
use JsonException;
use Log;
/**
* Class Sha3SignatureGenerator
@@ -41,8 +44,11 @@ class Sha3SignatureGenerator implements SignatureGeneratorInterface
try {
$json = json_encode($message->message, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
// See reference nr. 87
return sprintf('t=1,v%d=err-invalid-signature', $this->getVersion());
Log::error('Could not generate hash.');
Log::error(sprintf('JSON value: %s', $message->message));
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
throw new FireflyException('Could not generate JSON for SHA3 hash.', $e);
}
// signature v1 is generated using the following structure:

View File

@@ -1,66 +0,0 @@
<?php
/**
* TelemetryController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Admin;
use FireflyIII\Http\Controllers\Controller;
/**
* Class TelemetryController
*/
class TelemetryController extends Controller
{
/**
* TelemetryController constructor.
*/
public function __construct()
{
if (false === config('firefly.feature_flags.telemetry')) {
die('Telemetry is disabled.');
}
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.administration'));
app('view')->share('mainTitleIcon', 'fa-hand-spock-o');
return $next($request);
}
);
}
/**
* Index
*/
public function index()
{
app('view')->share('subTitleIcon', 'fa-eye');
app('view')->share('subTitle', (string)trans('firefly.telemetry_admin_index'));
$version = config('firefly.version');
$enabled = config('firefly.send_telemetry', false) && config('firefly.feature_flags.telemetry');
return prefixView('admin.telemetry.index', compact('version', 'enabled'));
}
}

View File

@@ -30,7 +30,6 @@ use Illuminate\Contracts\View\Factory;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
use Illuminate\View\View;
use Log;
@@ -93,15 +92,12 @@ class ForgotPasswordController extends Controller
// We will send the password reset link to this user. Once we have attempted
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$response = $this->broker()->sendResetLink(
$request->only('email')
);
$this->broker()->sendResetLink($request->only('email'));
if ($response === Password::RESET_LINK_SENT) {
return back()->with('status', trans($response));
}
// always send the same response:
$response = trans('firefly.forgot_password_response');
return back()->withErrors(['email' => trans($response)]);
return back()->with('status', trans($response));
}
/**

View File

@@ -29,6 +29,7 @@ use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Providers\RouteServiceProvider;
use Illuminate\Contracts\View\Factory;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -47,7 +48,7 @@ use Log;
*/
class LoginController extends Controller
{
use AuthenticatesUsers;
use AuthenticatesUsers, ThrottlesLogins;
/**
* Where to redirect users after login.

View File

@@ -69,6 +69,7 @@ class RegisterController extends Controller
if ('eloquent' !== $loginProvider || 'web' !== $authGuard) {
throw new FireflyException('Using external identity provider. Cannot continue.');
}
}
/**
@@ -84,21 +85,19 @@ class RegisterController extends Controller
{
// is allowed to?
$allowRegistration = true;
$loginProvider = config('firefly.login_provider');
$singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
if (true === $singleUserMode && $userCount > 0 && 'eloquent' === $loginProvider) {
$guard = config('auth.defaults.guard');
if (true === $singleUserMode && $userCount > 0 && 'ldap' !== $guard) {
$allowRegistration = false;
}
if ('eloquent' !== $loginProvider) {
if ('ldap' === $guard) {
$allowRegistration = false;
}
if (false === $allowRegistration) {
$message = 'Registration is currently not available.';
return prefixView('error', compact('message'));
throw new FireflyException('Registration is currently not available :(');
}
$this->validator($request->all())->validate();
@@ -126,21 +125,21 @@ class RegisterController extends Controller
public function showRegistrationForm(Request $request)
{
$allowRegistration = true;
$loginProvider = config('firefly.login_provider');
$isDemoSite = app('fireflyconfig')->get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
$singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
$pageTitle = (string)trans('firefly.register_page_title');
$guard = config('auth.defaults.guard');
if (true === $isDemoSite) {
$allowRegistration = false;
}
if (true === $singleUserMode && $userCount > 0 && 'eloquent' === $loginProvider) {
if (true === $singleUserMode && $userCount > 0 && 'ldap' !== $guard) {
$allowRegistration = false;
}
if ('eloquent' !== $loginProvider) {
if ('ldap' === $guard) {
$allowRegistration = false;
}

View File

@@ -87,7 +87,6 @@ class ResetPasswordController extends Controller
return prefixView('error', compact('message'));
}
$rules = [
'token' => 'required',
'email' => 'required|email',

View File

@@ -107,18 +107,18 @@ class IndexController extends Controller
'object_group_title' => $array['object_group_title'],
'bills' => [],
];
// expected today? default:
$array['next_expected_match_diff'] = trans('firefly.not_expected_period');
$nextExpectedMatch = new Carbon($array['next_expected_match']);
if ($nextExpectedMatch->isToday()) {
$array['next_expected_match_diff'] = trans('firefly.today');
}
$current = $array['pay_dates'][0] ?? null;
if (null !== $current && !$nextExpectedMatch->isToday()) {
$currentExpectedMatch = Carbon::createFromFormat('Y-m-d\TH:i:sP', $current);
$array['next_expected_match_diff'] = $currentExpectedMatch->diffForHumans(today(), Carbon::DIFF_RELATIVE_TO_NOW);
}
// var_dump($array);exit;
// // expected today? default:
// $array['next_expected_match_diff'] = trans('firefly.not_expected_period');
// $nextExpectedMatch = new Carbon($array['next_expected_match']);
// if ($nextExpectedMatch->isToday()) {
// $array['next_expected_match_diff'] = trans('firefly.today');
// }
// $current = $array['pay_dates'][0] ?? null;
// if (null !== $current && !$nextExpectedMatch->isToday()) {
// $currentExpectedMatch = Carbon::createFromFormat('Y-m-d\TH:i:sP', $current);
// $array['next_expected_match_diff'] = $currentExpectedMatch->diffForHumans(today(), Carbon::DIFF_RELATIVE_TO_NOW);
// }
$currency = $bill->transactionCurrency ?? $defaultCurrency;
$array['currency_id'] = $currency->id;

View File

@@ -150,7 +150,6 @@ class DebugController extends Controller
$foundDBversion = FireflyConfig::get('db_version', 1)->data;
// some new vars.
$telemetry = true === config('firefly.send_telemetry') && true === config('firefly.feature_flags.telemetry');
$defaultLanguage = (string)config('firefly.default_language');
$defaultLocale = (string)config('firefly.default_locale');
$userLanguage = app('steam')->getLanguage();
@@ -218,7 +217,6 @@ class DebugController extends Controller
'logContent',
'cacheDriver',
'trustedProxies',
'telemetry',
'userLanguage',
'userLocale',
'defaultLanguage',

View File

@@ -166,9 +166,13 @@ class PreferencesController extends Controller
// custom fiscal year
$customFiscalYear = 1 === (int)$request->get('customFiscalYear');
$fiscalYearStart = date('m-d', strtotime((string)$request->get('fiscalYearStart')));
app('preferences')->set('customFiscalYear', $customFiscalYear);
app('preferences')->set('fiscalYearStart', $fiscalYearStart);
$string = strtotime((string)$request->get('fiscalYearStart'));
if(false !== $string) {
$fiscalYearStart = date('m-d', $string);
app('preferences')->set('customFiscalYear', $customFiscalYear);
app('preferences')->set('fiscalYearStart', $fiscalYearStart);
}
// save page size:
app('preferences')->set('listPageSize', 50);

View File

@@ -30,6 +30,7 @@ use FireflyIII\Http\Requests\RecurrenceFormRequest;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use Illuminate\Contracts\View\Factory;
@@ -47,6 +48,7 @@ class CreateController extends Controller
private AttachmentHelperInterface $attachments;
private BudgetRepositoryInterface $budgetRepos;
private RecurringRepositoryInterface $recurring;
private BillRepositoryInterface $billRepository;
/**
* CreateController constructor.
@@ -64,9 +66,10 @@ class CreateController extends Controller
app('view')->share('title', (string)trans('firefly.recurrences'));
app('view')->share('subTitle', (string)trans('firefly.create_new_recurrence'));
$this->recurring = app(RecurringRepositoryInterface::class);
$this->budgetRepos = app(BudgetRepositoryInterface::class);
$this->attachments = app(AttachmentHelperInterface::class);
$this->recurring = app(RecurringRepositoryInterface::class);
$this->budgetRepos = app(BudgetRepositoryInterface::class);
$this->attachments = app(AttachmentHelperInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
return $next($request);
}
@@ -83,6 +86,7 @@ class CreateController extends Controller
public function create(Request $request)
{
$budgets = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets());
$bills = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills());
$defaultCurrency = app('amount')->getDefaultCurrency();
$tomorrow = today(config('app.timezone'));
$oldRepetitionType = $request->old('repetition_type');
@@ -115,7 +119,7 @@ class CreateController extends Controller
return prefixView(
'recurring.create',
compact('tomorrow', 'oldRepetitionType', 'weekendResponses', 'preFilled', 'repetitionEnds', 'defaultCurrency', 'budgets')
compact('tomorrow', 'oldRepetitionType', 'bills', 'weekendResponses', 'preFilled', 'repetitionEnds', 'defaultCurrency', 'budgets')
);
}
@@ -155,11 +159,12 @@ class CreateController extends Controller
$type = strtolower($journal->transactionType->type);
/** @var Transaction $source */
$source = $journal->transactions()->where('amount', '<', 0)->first();
$source = $journal->transactions()->where('amount', '<', 0)->first();
/** @var Transaction $dest */
$dest = $journal->transactions()->where('amount', '>', 0)->first();
$category = $journal->categories()->first() ? $journal->categories()->first()->name : '';
$budget = $journal->budgets()->first() ? $journal->budgets()->first()->id : 0;
$bill = $journal->bill ? $journal->bill->id : 0;
$hasOldInput = null !== $request->old('_token'); // flash some data
$preFilled = [];
if (true === $hasOldInput) {
@@ -178,6 +183,7 @@ class CreateController extends Controller
'transaction_type' => $request->old('transaction_type'),
'category' => $request->old('category'),
'budget_id' => $request->old('budget_id'),
'bill_id' => $request->old('bill_id'),
'active' => (bool)$request->old('active'),
'apply_rules' => (bool)$request->old('apply_rules'),
];
@@ -198,6 +204,7 @@ class CreateController extends Controller
'transaction_type' => $type,
'category' => $category,
'budget_id' => $budget,
'bill_id' => $bill,
'active' => true,
'apply_rules' => true,
];
@@ -243,7 +250,7 @@ class CreateController extends Controller
}
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments'));
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments'));
}
$redirect = redirect($this->getPreviousUri('recurring.create.uri'));

View File

@@ -29,6 +29,7 @@ use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\RecurrenceFormRequest;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Transformers\RecurrenceTransformer;
@@ -48,6 +49,7 @@ class EditController extends Controller
private AttachmentHelperInterface $attachments;
private BudgetRepositoryInterface $budgetRepos;
private RecurringRepositoryInterface $recurring;
private BillRepositoryInterface $billRepository;
/**
* EditController constructor.
@@ -65,9 +67,10 @@ class EditController extends Controller
app('view')->share('title', (string)trans('firefly.recurrences'));
app('view')->share('subTitle', (string)trans('firefly.recurrences'));
$this->recurring = app(RecurringRepositoryInterface::class);
$this->budgetRepos = app(BudgetRepositoryInterface::class);
$this->attachments = app(AttachmentHelperInterface::class);
$this->recurring = app(RecurringRepositoryInterface::class);
$this->budgetRepos = app(BudgetRepositoryInterface::class);
$this->attachments = app(AttachmentHelperInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
return $next($request);
}
@@ -86,7 +89,7 @@ class EditController extends Controller
*/
public function edit(Request $request, Recurrence $recurrence)
{
// See reference nr. 69
// See reference nr. 69
$count = $recurrence->recurrenceTransactions()->count();
if (0 === $count) {
throw new FireflyException('This recurring transaction has no meta-data. You will have to delete it and recreate it. Sorry!');
@@ -98,6 +101,7 @@ class EditController extends Controller
$array = $transformer->transform($recurrence);
$budgets = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets());
$bills = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills());
/** @var RecurrenceRepetition $repetition */
$repetition = $recurrence->recurrenceRepetitions()->first();
@@ -146,7 +150,10 @@ class EditController extends Controller
return prefixView(
'recurring.edit',
compact('recurrence', 'array', 'weekendResponses', 'budgets', 'preFilled', 'currentRepType', 'repetitionEnd', 'repetitionEnds')
compact(
'recurrence', 'array', 'bills',
'weekendResponses', 'budgets', 'preFilled', 'currentRepType', 'repetitionEnd', 'repetitionEnds'
)
);
}

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Http\Middleware;
use Closure;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Http\Request;
@@ -58,6 +59,10 @@ class InterestingMessage
Preferences::mark();
$this->handleAccountMessage($request);
}
if ($this->billMessage($request)) {
Preferences::mark();
$this->handleBillMessage($request);
}
return $next($request);
}
@@ -88,11 +93,12 @@ class InterestingMessage
/**
* @param Request $request
*/
private function handleAccountMessage(Request $request): void {
private function handleAccountMessage(Request $request): void
{
// get parameters from request.
$accountId = $request->get('account_id');
$message = $request->get('message');
$message = $request->get('message');
/** @var Account $account */
$account = auth()->user()->accounts()->withTrashed()->find($accountId);
@@ -103,10 +109,38 @@ class InterestingMessage
if ('deleted' === $message) {
session()->flash('success', (string)trans('firefly.account_deleted', ['name' => $account->name]));
}
if('created' === $message) {
if ('created' === $message) {
session()->flash('success', (string)trans('firefly.stored_new_account', ['name' => $account->name]));
}
if ('updated' === $message) {
session()->flash('success', (string)trans('firefly.updated_account', ['name' => $account->name]));
}
}
/**
* @param Request $request
*/
private function handleBillMessage(Request $request): void
{
// get parameters from request.
$billId = $request->get('bill_id');
$message = $request->get('message');
/** @var Bill $bill */
$bill = auth()->user()->bills()->withTrashed()->find($billId);
if (null === $bill) {
return;
}
if ('deleted' === $message) {
session()->flash('success', (string)trans('firefly.deleted_bill', ['name' => $bill->name]));
}
if ('created' === $message) {
session()->flash('success', (string)trans('firefly.stored_new_bill', ['name' => $bill->name]));
}
}
/**
* @param Request $request
*/
@@ -162,4 +196,18 @@ class InterestingMessage
return null !== $accountId && null !== $message;
}
/**
* @param Request $request
*
* @return bool
*/
private function billMessage(Request $request): bool
{
// get parameters from request.
$billId = $request->get('bill_id');
$message = $request->get('message');
return null !== $billId && null !== $message;
}
}

View File

@@ -46,11 +46,13 @@ class StartFireflySession extends StartSession
$isDeletePage = strpos($uri, 'delete');
$isLoginPage = strpos($uri, '/login');
$isJsonPage = strpos($uri, '/json');
$isView = strpos($uri, '/attachments/view');
// also stop remembering "delete" URL's.
if (false === $isScriptPage && false === $isDeletePage
&& false === $isLoginPage
&& false === $isJsonPage
&& false === $isView
&& 'GET' === $request->method()
&& !$request->ajax()) {
$session->setPreviousUrl($uri);

View File

@@ -78,6 +78,8 @@ class RecurrenceFormRequest extends FormRequest
'foreign_currency_code' => null,
'budget_id' => $this->integer('budget_id'),
'budget_name' => null,
'bill_id' => $this->integer('bill_id'),
'bill_name' => null,
'category_id' => null,
'category_name' => $this->string('category'),
'tags' => '' !== $this->string('tags') ? explode(',', $this->string('tags')) : [],
@@ -109,7 +111,7 @@ class RecurrenceFormRequest extends FormRequest
// fill in source and destination account data
switch ($this->string('transaction_type')) {
default:
throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->string('transaction_type')));
throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->string('transaction_type')));
case 'withdrawal':
$return['transactions'][0]['source_id'] = $this->integer('source_id');
$return['transactions'][0]['destination_id'] = $this->integer('withdrawal_destination_id');
@@ -162,11 +164,11 @@ class RecurrenceFormRequest extends FormRequest
$return['type'] = substr($value, 0, 6);
$return['moment'] = substr($value, 7);
}
if (0 === strpos($value, 'monthly')) {
if (str_starts_with($value, 'monthly')) {
$return['type'] = substr($value, 0, 7);
$return['moment'] = substr($value, 8);
}
if (0 === strpos($value, 'ndom')) {
if (str_starts_with($value, 'ndom')) {
$return['type'] = substr($value, 0, 4);
$return['moment'] = substr($value, 5);
}
@@ -213,6 +215,7 @@ class RecurrenceFormRequest extends FormRequest
// optional fields:
'budget_id' => 'mustExist:budgets,id|belongsToUser:budgets,id|nullable',
'bill_id' => 'mustExist:bills,id|belongsToUser:bills,id|nullable',
'category' => 'between:1,255|nullable',
'tags' => 'between:1,255|nullable',
];
@@ -251,7 +254,7 @@ class RecurrenceFormRequest extends FormRequest
break;
default:
throw new FireflyException(sprintf('Cannot handle transaction type of type "%s"', $this->string('transaction_type')));
throw new FireflyException(sprintf('Cannot handle transaction type of type "%s"', $this->string('transaction_type')));
}
// update some rules in case the user is editing a post:
@@ -304,11 +307,11 @@ class RecurrenceFormRequest extends FormRequest
$sourceId = null;
$destinationId = null;
// See reference nr. 45
// See reference nr. 45
switch ($this->string('transaction_type')) {
default:
throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->string('transaction_type')));
throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->string('transaction_type')));
case 'withdrawal':
$sourceId = (int)$data['source_id'];
$destinationId = (int)$data['withdrawal_destination_id'];

View File

@@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/*
* AttributeHandler.php
* Copyright (c) 2021 james@firefly-iii.org
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Ldap;
use FireflyIII\User as DatabaseUser;

View File

@@ -110,6 +110,8 @@ class Bill extends Model
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'date' => 'date',
'end_date' => 'date',
'extension_date' => 'date',
'skip' => 'int',
'automatch' => 'boolean',
'active' => 'boolean',
@@ -120,7 +122,7 @@ class Bill extends Model
/** @var array Fields that can be filled */
protected $fillable
= ['name', 'match', 'amount_min', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip',
'automatch', 'active', 'transaction_currency_id'];
'automatch', 'active', 'transaction_currency_id', 'end_date', 'extension_date'];
/** @var array Hidden from view */
protected $hidden = ['amount_min_encrypted', 'amount_max_encrypted', 'name_encrypted', 'match_encrypted'];

View File

@@ -1,75 +0,0 @@
<?php
/**
* Telemetry.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
/**
* FireflyIII\Models\Telemetry
*
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $submitted
* @property int|null $user_id
* @property string $installation_id
* @property string $type
* @property string $key
* @property array $value
* @method static Builder|Telemetry newModelQuery()
* @method static Builder|Telemetry newQuery()
* @method static Builder|Telemetry query()
* @method static Builder|Telemetry whereCreatedAt($value)
* @method static Builder|Telemetry whereId($value)
* @method static Builder|Telemetry whereInstallationId($value)
* @method static Builder|Telemetry whereKey($value)
* @method static Builder|Telemetry whereSubmitted($value)
* @method static Builder|Telemetry whereType($value)
* @method static Builder|Telemetry whereUpdatedAt($value)
* @method static Builder|Telemetry whereUserId($value)
* @method static Builder|Telemetry whereValue($value)
* @mixin Eloquent
*/
class Telemetry extends Model
{
/** @var string */
protected $table = 'telemetry';
/** @var array */
protected $fillable = ['installation_id', 'submitted', 'user_id', 'key', 'type', 'value'];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts
= [
'submitted' => 'datetime',
'value' => 'array',
];
}

View File

@@ -44,6 +44,7 @@ use Illuminate\Auth\Events\Login;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Laravel\Passport\Client;
use Laravel\Passport\Events\AccessTokenCreated;
use LdapRecord\Laravel\Events\Import\Imported;
use Log;
use Mail;
use Request;
@@ -130,6 +131,11 @@ class EventServiceProvider extends ServiceProvider
UpdatedAccount::class => [
'FireflyIII\Handlers\Events\UpdatedAccountEventHandler@recalculateCredit',
],
// LDAP related events:
Imported::class => [
'FireflyIII\Handlers\Events\LDAPEventHandler@importedUser',
],
];
/**

View File

@@ -64,7 +64,6 @@ use FireflyIII\Support\Form\RuleForm;
use FireflyIII\Support\Navigation;
use FireflyIII\Support\Preferences;
use FireflyIII\Support\Steam;
use FireflyIII\Support\Telemetry;
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
use FireflyIII\TransactionRules\Engine\SearchRuleEngine;
use FireflyIII\Validation\FireflyValidator;
@@ -165,13 +164,6 @@ class FireflyServiceProvider extends ServiceProvider
}
);
$this->app->bind(
'telemetry',
static function () {
return new Telemetry;
}
);
// chart generator:
$this->app->bind(GeneratorInterface::class, ChartJsGenerator::class);
// other generators

View File

@@ -149,21 +149,17 @@ class AccountRepository implements AccountRepositoryInterface
}
Log::debug(sprintf('Searching for account named "%s" (of user #%d) of the following type(s)', $name, $this->user->id), ['types' => $types]);
$accounts = $query->get(['accounts.*']);
// See reference nr. 10
$query->where('accounts.name', $name);
/** @var Account $account */
foreach ($accounts as $account) {
if ($account->name === $name) {
Log::debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id));
$account = $query->first(['accounts.*']);
if (null === $account) {
Log::debug(sprintf('There is no account with name "%s" of types', $name), $types);
return $account;
}
return null;
}
Log::debug(sprintf('There is no account with name "%s" of types', $name), $types);
Log::debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id));
return null;
return $account;
}
/**

View File

@@ -72,7 +72,7 @@ interface BudgetLimitRepositoryInterface
public function find(Budget $budget, TransactionCurrency $currency, Carbon $start, Carbon $end): ?BudgetLimit;
/**
* See reference nr. 11
* See reference nr. 11
*
* @param Carbon|null $start
* @param Carbon|null $end

View File

@@ -99,8 +99,6 @@ interface JournalRepositoryInterface
public function getLast(): ?TransactionJournal;
/**
* See reference nr. 4
*
* @param TransactionJournalLink $link
*
* @return string

View File

@@ -24,8 +24,6 @@ namespace FireflyIII\Repositories\LinkType;
use Exception;
use FireflyIII\Events\DestroyedTransactionLink;
use FireflyIII\Events\StoredTransactionLink;
use FireflyIII\Events\UpdatedTransactionLink;
use FireflyIII\Models\LinkType;
use FireflyIII\Models\Note;
use FireflyIII\Models\TransactionJournal;
@@ -281,8 +279,6 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface
// make note in noteable:
$this->setNoteText($link, (string)$information['notes']);
event(new StoredTransactionLink($link));
return $link;
}
@@ -352,8 +348,6 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface
$this->setNoteText($journalLink, $data['notes']);
}
event(new UpdatedTransactionLink($journalLink));
return $journalLink;
}

View File

@@ -23,6 +23,7 @@
declare(strict_types=1);
namespace FireflyIII\Repositories\PiggyBank;
use Carbon\Carbon;
use Exception;
use FireflyIII\Exceptions\FireflyException;
@@ -90,7 +91,7 @@ trait ModifiesPiggyBanks
$leftOnAccount = $this->leftOnAccount($piggyBank, today(config('app.timezone')));
$savedSoFar = (string)$this->getRepetition($piggyBank)->currentamount;
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
$maxAmount = (string)min(round((float)$leftOnAccount, 12), round((float)$leftToSave, 12));
$maxAmount = 1 === bccomp($leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
$compare = bccomp($amount, $maxAmount);
$result = $compare <= 0;
@@ -304,7 +305,7 @@ trait ModifiesPiggyBanks
$piggyBank = PiggyBank::create($piggyData);
} catch (QueryException $e) {
Log::error(sprintf('Could not store piggy bank: %s', $e->getMessage()), $piggyData);
throw new FireflyException('400005: Could not store new piggy bank.',0,$e);
throw new FireflyException('400005: Could not store new piggy bank.', 0, $e);
}
// reset order then set order:
@@ -315,7 +316,7 @@ trait ModifiesPiggyBanks
// repetition is auto created.
$repetition = $this->getRepetition($piggyBank);
if (null !== $repetition && array_key_exists('current_amount',$data) && '' !== $data['current_amount']) {
if (null !== $repetition && array_key_exists('current_amount', $data) && '' !== $data['current_amount']) {
$repetition->currentamount = $data['current_amount'];
$repetition->save();
}

View File

@@ -61,6 +61,7 @@ class TagRepository implements TagRepositoryInterface
*/
public function destroy(Tag $tag): bool
{
DB::table('tag_transaction_journal')->where('tag_id', $tag->id)->delete();
$tag->transactionJournals()->sync([]);
$tag->delete();

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Rules;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use Illuminate\Contracts\Validation\Rule;
use Log;
@@ -67,6 +68,10 @@ class IsDateOrTime implements Rule
} catch (InvalidDateException $e) {
Log::error(sprintf('"%s" is not a valid date: %s', $value, $e->getMessage()));
return false;
} catch(InvalidFormatException $e) {
Log::error(sprintf('"%s" is of an invalid format: %s', $value, $e->getMessage()));
return false;
}
@@ -78,6 +83,10 @@ class IsDateOrTime implements Rule
} catch (InvalidDateException $e) {
Log::error(sprintf('"%s" is not a valid date or time: %s', $value, $e->getMessage()));
return false;
} catch(InvalidFormatException $e) {
Log::error(sprintf('"%s" is of an invalid format: %s', $value, $e->getMessage()));
return false;
}

View File

@@ -0,0 +1,116 @@
<?php
/*
* IsValidBulkClause.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Validator;
use JsonException;
/**
* Class IsValidBulkClause
*/
class IsValidBulkClause implements Rule
{
private array $rules;
private string $error;
/**
* @param string $type
*/
public function __construct(string $type)
{
$this->rules = config(sprintf('bulk.%s', $type));
$this->error = (string)trans('firefly.belongs_user');
}
/**
* @param string $attribute
* @param mixed $value
*
* @return bool
*/
public function passes($attribute, $value): bool
{
$result = $this->basicValidation((string)$value);
if (false === $result) {
return false;
}
return true;
}
/**
* @return string
*/
public function message(): string
{
return $this->error;
}
/**
* Does basic rule based validation.
*
* @return bool
*/
private function basicValidation(string $value): bool
{
try {
$array = json_decode($value, true, 8, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
$this->error = (string)trans('validation.json');
return false;
}
$clauses = ['where', 'update'];
foreach ($clauses as $clause) {
if (!array_key_exists($clause, $array)) {
$this->error = (string)trans(sprintf('validation.missing_%s', $clause));
return false;
}
/**
* @var string $arrayKey
* @var mixed $arrayValue
*/
foreach ($array[$clause] as $arrayKey => $arrayValue) {
if (!array_key_exists($arrayKey, $this->rules[$clause])) {
$this->error = (string)trans(sprintf('validation.invalid_%s_key', $clause));
return false;
}
// validate!
$validator = Validator::make(['value' => $arrayValue], [
'value' => $this->rules[$clause][$arrayKey],
]);
if ($validator->fails()) {
$this->error = sprintf('%s: %s: %s',$clause, $arrayKey, join(', ', ($validator->errors()->get('value'))));
return false;
}
}
}
return true;
}
}

View File

@@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/*
* CreditRecalculateService.php
* Copyright (c) 2021 james@firefly-iii.org
@@ -20,6 +20,9 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Internal\Support;

View File

@@ -74,7 +74,7 @@ trait JournalServiceTrait
// and now try to find it, based on the type of transaction.
$message = 'Based on the fact that the transaction is a %s, the %s account should be in: %s. Direction is %s.';
Log::debug(sprintf($message, $transactionType, $direction, implode(', ', $expectedTypes[$transactionType]), $direction));
Log::debug(sprintf($message, $transactionType, $direction, implode(', ', $expectedTypes[$transactionType] ?? ['UNKNOWN']), $direction));
$result = $this->findAccountById($data, $expectedTypes[$transactionType]);
$result = $this->findAccountByName($result, $data, $expectedTypes[$transactionType]);

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Services\Internal\Support;
use Exception;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory;
use FireflyIII\Factory\BillFactory;
use FireflyIII\Factory\BudgetFactory;
use FireflyIII\Factory\CategoryFactory;
use FireflyIII\Factory\PiggyBankFactory;
@@ -136,16 +137,16 @@ trait RecurringTransactionTrait
$validator->setUser($recurrence->user);
$validator->setTransactionType($recurrence->transactionType->type);
if (!$validator->validateSource($source->id, null, null)) {
throw new FireflyException(sprintf('Source invalid: %s', $validator->sourceError));
throw new FireflyException(sprintf('Source invalid: %s', $validator->sourceError));
}
if (!$validator->validateDestination($destination->id, null, null)) {
throw new FireflyException(sprintf('Destination invalid: %s', $validator->destError));
throw new FireflyException(sprintf('Destination invalid: %s', $validator->destError));
}
if (array_key_exists('foreign_amount', $array) && '' === (string)$array['foreign_amount']) {
unset($array['foreign_amount']);
}
// See reference nr. 100
// See reference nr. 100
$transaction = new RecurrenceTransaction(
[
'recurrence_id' => $recurrence->id,
@@ -163,6 +164,9 @@ trait RecurringTransactionTrait
if (array_key_exists('budget_id', $array)) {
$this->setBudget($transaction, (int)$array['budget_id']);
}
if (array_key_exists('bill_id', $array)) {
$this->setBill($transaction, (int)$array['bill_id']);
}
if (array_key_exists('category_id', $array)) {
$this->setCategory($transaction, (int)$array['category_id']);
}
@@ -254,6 +258,29 @@ trait RecurringTransactionTrait
$meta->save();
}
/**
* @param RecurrenceTransaction $transaction
* @param int $billId
*/
private function setBill(RecurrenceTransaction $transaction, int $billId): void
{
$billFactory = app(BillFactory::class);
$billFactory->setUser($transaction->recurrence->user);
$bill = $billFactory->find($billId, null);
if (null === $bill) {
return;
}
$meta = $transaction->recurrenceTransactionMeta()->where('name', 'bill_id')->first();
if (null === $meta) {
$meta = new RecurrenceTransactionMeta;
$meta->rt_id = $transaction->id;
$meta->name = 'bill_id';
}
$meta->value = $bill->id;
$meta->save();
}
/**
* @param RecurrenceTransaction $transaction
* @param int $categoryId
@@ -269,6 +296,7 @@ trait RecurringTransactionTrait
// remove category:
$transaction->recurrenceTransactionMeta()->where('name', 'category_id')->delete();
$transaction->recurrenceTransactionMeta()->where('name', 'category_name')->delete();
return;
}

View File

@@ -35,7 +35,6 @@ use FireflyIII\Models\TransactionJournalMeta;
/**
* Class GroupCloneService
* See reference nr. 92
*/
class GroupCloneService
{

View File

@@ -32,7 +32,6 @@ use Log;
/**
* Class GroupUpdateService
* See reference nr. 91
*/
class GroupUpdateService
{

View File

@@ -48,7 +48,6 @@ use Log;
* Class to centralise code that updates a journal given the input by system.
*
* Class JournalUpdateService
* See reference nr. 93
*/
class JournalUpdateService
{
@@ -163,8 +162,6 @@ class JournalUpdateService
$this->updateAmount();
$this->updateForeignAmount();
// See reference nr. 94
app('preferences')->mark();
$this->transactionJournal->refresh();

View File

@@ -289,6 +289,9 @@ class RecurrenceUpdateService
if (array_key_exists('budget_id', $current)) {
$this->setBudget($match, (int)$current['budget_id']);
}
if (array_key_exists('bill_id', $current)) {
$this->setBill($match, (int)$current['bill_id']);
}
// reset category if name is set but empty:
// can be removed when v1 is retired.
if (array_key_exists('category_name', $current) && '' === (string)$current['category_name']) {

View File

@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
/*
* StaticConfigKey.php
* EitherConfigKey.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Binder;
use Illuminate\Routing\Route;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -38,8 +40,10 @@ class EitherConfigKey
'firefly.accountRoles',
'firefly.valid_liabilities',
'firefly.interest_periods',
'firefly.bill_periods',
'firefly.enable_external_map',
'firefly.expected_source_types',
'firefly.credit_card_types',
'app.timezone',
];
/**

View File

@@ -58,9 +58,9 @@ class ExpandedForm
unset($options['currency'], $options['placeholder']);
// make sure value is formatted nicely:
if (null !== $value && '' !== $value) {
$value = round((float)$value, 8);
}
//if (null !== $value && '' !== $value) {
//$value = round((float)$value, 8);
//}
try {
$html = prefixView('form.amount-no-currency', compact('classes', 'name', 'label', 'value', 'options'))->render();
} catch (Throwable $e) { // @phpstan-ignore-line
@@ -224,6 +224,7 @@ class ExpandedForm
}
$selectList[$entryId] = $title;
}
return $selectList;
}
@@ -246,7 +247,7 @@ class ExpandedForm
// make sure value is formatted nicely:
if (null !== $value && '' !== $value) {
$value = round((float)$value, $selectedCurrency->decimal_places);
// $value = round((float)$value, $selectedCurrency->decimal_places);
}
try {
$html = prefixView('form.non-selectable-amount', compact('selectedCurrency', 'classes', 'name', 'label', 'value', 'options'))->render();

View File

@@ -34,8 +34,6 @@ use Throwable;
* Class CurrencyForm
*
* All currency related form methods.
*
* See reference nr. 22
*/
class CurrencyForm
{
@@ -61,7 +59,7 @@ class CurrencyForm
*
* @return string
*/
protected function currencyField(string $name, string $view, $value = null, array $options = null): string
protected function currencyField(string $name, string $view, mixed $value = null, array $options = null): string
{
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);

View File

@@ -130,8 +130,8 @@ trait ModelInformation
$billTriggers = ['currency_is', 'amount_more', 'amount_less', 'description_contains'];
$values = [
$bill->transactionCurrency()->first()->name,
round((float)$bill->amount_min, 12),
round((float)$bill->amount_max, 12),
round((float)$bill->amount_min, 24),
round((float)$bill->amount_max, 24),
$bill->name,
];
foreach ($billTriggers as $index => $trigger) {

View File

@@ -38,7 +38,7 @@ use Log;
/**
* Trait PeriodOverview.
*
* See reference nr. 36
* See reference nr. 36
*
* - Always request start date and end date.
* - Group expenses, income, etc. under this period.
@@ -91,7 +91,7 @@ trait PeriodOverview
$cache->addProperty('account-show-period-entries');
$cache->addProperty($account->id);
if ($cache->has()) {
return $cache->get();
return $cache->get();
}
/** @var array $dates */
$dates = app('navigation')->blockPeriods($start, $end, $range);
@@ -284,7 +284,7 @@ trait PeriodOverview
$cache->addProperty($category->id);
if ($cache->has()) {
return $cache->get();
return $cache->get();
}
/** @var array $dates */
$dates = app('navigation')->blockPeriods($start, $end, $range);
@@ -360,7 +360,7 @@ trait PeriodOverview
$cache->addProperty('no-budget-period-entries');
if ($cache->has()) {
return $cache->get();
return $cache->get();
}
/** @var array $dates */
@@ -392,7 +392,7 @@ trait PeriodOverview
}
/**
* See reference nr. 37
* See reference nr. 37
*
* Show period overview for no category view.
*
@@ -419,7 +419,7 @@ trait PeriodOverview
$cache->addProperty('no-category-period-entries');
if ($cache->has()) {
return $cache->get();
return $cache->get();
}
$dates = app('navigation')->blockPeriods($start, $end, $range);
@@ -494,7 +494,7 @@ trait PeriodOverview
$cache->addProperty('tag-period-entries');
$cache->addProperty($tag->id);
if ($cache->has()) {
return $cache->get();
return $cache->get();
}
/** @var array $dates */
$dates = app('navigation')->blockPeriods($start, $end, $range);
@@ -568,7 +568,7 @@ trait PeriodOverview
$cache->addProperty('transactions-period-entries');
$cache->addProperty($transactionType);
if ($cache->has()) {
return $cache->get();
return $cache->get();
}
/** @var array $dates */
$dates = app('navigation')->blockPeriods($start, $end, $range);

View File

@@ -29,6 +29,7 @@ use FireflyIII\Models\Preference;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Log;
use PDOException;
use Session;
/**
@@ -144,6 +145,19 @@ class Preferences
return $result;
}
/**
* @return Collection
*/
public function all(): Collection
{
$user = auth()->user();
if(null === $user) {
return new Collection;
}
return Preference::where('user_id', $user->id)->get();
}
/**
* @param User $user
* @param string $name
@@ -284,7 +298,11 @@ class Preferences
$pref->name = $name;
}
$pref->data = $value;
$pref->save();
try {
$pref->save();
} catch(PDOException $e) {
throw new FireflyException(sprintf('Could not save preference: %s', $e->getMessage()), 0, $e);
}
Cache::forever($fullName, $pref);
return $pref;

View File

@@ -1,88 +0,0 @@
<?php
/**
* Telemetry.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support;
use Carbon\Carbon;
use FireflyIII\Support\System\GeneratesInstallationId;
use Sentry\Severity;
use Sentry\State\Scope;
use function Sentry\captureMessage;
use function Sentry\configureScope;
/**
* Class Telemetry
*/
class Telemetry
{
use GeneratesInstallationId;
/**
* Feature telemetry stores a $value for the given $feature.
* Will only store the given $feature / $value combination once.
*
*
* Examples:
* - execute-cli-command [value]
* - use-help-pages
* - has-created-bill
* - first-time-install
* - more
*
* Its use should be limited to exotic and strange use cases in Firefly III.
* Because time and date are logged as well, useful to track users' evolution in Firefly III.
*
* Any meta-data stored is strictly non-financial.
*
* @param string $key
* @param string $value
*/
public function feature(string $key, string $value): void
{
if (false === config('firefly.send_telemetry') || false === config('firefly.feature_flags.telemetry')) {
// hard stop if not allowed to do telemetry.
// do nothing!
return;
}
$this->generateInstallationId();
$installationId = app('fireflyconfig')->get('installation_id');
// add some context:
configureScope(
function (Scope $scope) use ($installationId, $key, $value): void {
$scope->setContext(
'telemetry', [
'installation_id' => $installationId->data,
'version' => config('firefly.version'),
'collected_at' => Carbon::now()->format('r'),
'key' => $key,
'value' => $value,
]
);
}
);
captureMessage(sprintf('FIT: %s/%s', $key, $value), Severity::info());
}
}

View File

@@ -28,7 +28,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Search\OperatorQuerySearch;
use League\CommonMark\CommonMarkConverter;
use League\CommonMark\Environment;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
use Route;
use Twig\Extension\AbstractExtension;
@@ -203,14 +203,16 @@ class General extends AbstractExtension
protected function markdown(): TwigFilter
{
return new TwigFilter(
'markdown',
'markdown',
static function (string $text): string {
$environment = Environment::createCommonMarkEnvironment();
$environment->addExtension(new GithubFlavoredMarkdownExtension());
$converter = new CommonMarkConverter(['allow_unsafe_links' => false, 'max_nesting_level' => 3, 'html_input' => 'escape'], $environment);
return $converter->convertToHtml($text);
return (string) $converter->convertToHtml($text);
}, ['is_safe' => ['html']]
);
}
@@ -355,7 +357,7 @@ class General extends AbstractExtension
/**
* @return TwigFunction
* See reference nr. 43
* See reference nr. 43
*/
protected function getMetaField(): TwigFunction
{

View File

@@ -78,43 +78,62 @@ class BillTransformer extends AbstractTransformer
$paidDataFormatted = [];
$payDatesFormatted = [];
foreach($paidData['paid_dates'] as $object) {
$object['date'] = Carbon::createFromFormat('!Y-m-d', $object['date'], config('app.timezone'))->toAtomString();
$paidDataFormatted[] = $object;
foreach ($paidData['paid_dates'] as $object) {
$object['date'] = Carbon::createFromFormat('!Y-m-d', $object['date'], config('app.timezone'))->toAtomString();
$paidDataFormatted[] = $object;
}
foreach ($payDates as $string) {
$payDatesFormatted[] = Carbon::createFromFormat('!Y-m-d', $string, config('app.timezone'))->toAtomString();
}
$nextExpectedMatch = null;
if(null !== $paidData['next_expected_match'] ) {
if (null !== $paidData['next_expected_match']) {
$nextExpectedMatch = Carbon::createFromFormat('!Y-m-d', $paidData['next_expected_match'], config('app.timezone'))->toAtomString();
}
$nextExpectedMatchDiff = trans('firefly.not_expected_period');
// converting back and forth is bad code but OK.
$temp = new Carbon($nextExpectedMatch);
if ($temp->isToday()) {
$nextExpectedMatchDiff = trans('firefly.today');
}
$current = $payDatesFormatted[0] ?? null;
if (null !== $current && !$temp->isToday()) {
$temp2 = Carbon::createFromFormat('Y-m-d\TH:i:sP', $current);
$nextExpectedMatchDiff = $temp2->diffForHumans(today(), Carbon::DIFF_RELATIVE_TO_NOW);
}
unset($temp, $temp2);
return [
'id' => (int)$bill->id,
'created_at' => $bill->created_at->toAtomString(),
'updated_at' => $bill->updated_at->toAtomString(),
'currency_id' => (string)$bill->transaction_currency_id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => (int)$currency->decimal_places,
'name' => $bill->name,
'amount_min' => number_format((float)$bill->amount_min, $currency->decimal_places, '.', ''),
'amount_max' => number_format((float)$bill->amount_max, $currency->decimal_places, '.', ''),
'date' => $bill->date->toAtomString(),
'repeat_freq' => $bill->repeat_freq,
'skip' => (int)$bill->skip,
'active' => $bill->active,
'order' => (int)$bill->order,
'notes' => $notes,
'next_expected_match' => $nextExpectedMatch,
'pay_dates' => $payDatesFormatted,
'paid_dates' => $paidDataFormatted,
'object_group_id' => $objectGroupId ? (string)$objectGroupId : null,
'object_group_order' => $objectGroupOrder,
'object_group_title' => $objectGroupTitle,
'links' => [
'id' => (int)$bill->id,
'created_at' => $bill->created_at->toAtomString(),
'updated_at' => $bill->updated_at->toAtomString(),
'currency_id' => (string)$bill->transaction_currency_id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => (int)$currency->decimal_places,
'name' => $bill->name,
'amount_min' => number_format((float)$bill->amount_min, $currency->decimal_places, '.', ''),
'amount_max' => number_format((float)$bill->amount_max, $currency->decimal_places, '.', ''),
'date' => $bill->date->toAtomString(),
'end_date' => $bill->end_date?->toAtomString(),
'extension_date' => $bill->extension_date?->toAtomString(),
'repeat_freq' => $bill->repeat_freq,
'skip' => (int)$bill->skip,
'active' => $bill->active,
'order' => (int)$bill->order,
'notes' => $notes,
'object_group_id' => $objectGroupId ? (string)$objectGroupId : null,
'object_group_order' => $objectGroupOrder,
'object_group_title' => $objectGroupTitle,
// these fields need work:
'next_expected_match' => $nextExpectedMatch,
'next_expected_match_diff' => $nextExpectedMatchDiff,
'pay_dates' => $payDatesFormatted,
'paid_dates' => $paidDataFormatted,
'links' => [
[
'rel' => 'self',
'uri' => '/bills/' . $bill->id,
@@ -208,7 +227,7 @@ class BillTransformer extends AbstractTransformer
protected function lastPaidDate(Collection $dates, Carbon $default): Carbon
{
if (0 === $dates->count()) {
return $default;
return $default;
}
$latest = $dates->first()->date;
/** @var TransactionJournal $journal */
@@ -254,6 +273,7 @@ class BillTransformer extends AbstractTransformer
return $date->format('Y-m-d');
}
);
return $simple->toArray();
}

View File

@@ -22,6 +22,7 @@
declare(strict_types=1);
namespace FireflyIII\Transformers;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\CategoryFactory;
@@ -29,6 +30,7 @@ use FireflyIII\Models\Recurrence;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\RecurrenceTransactionMeta;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
@@ -44,6 +46,7 @@ class RecurrenceTransformer extends AbstractTransformer
private CategoryFactory $factory;
private PiggyBankRepositoryInterface $piggyRepos;
private RecurringRepositoryInterface $repository;
private BillRepositoryInterface $billRepos;
/**
* RecurrenceTransformer constructor.
@@ -56,6 +59,7 @@ class RecurrenceTransformer extends AbstractTransformer
$this->piggyRepos = app(PiggyBankRepositoryInterface::class);
$this->factory = app(CategoryFactory::class);
$this->budgetRepos = app(BudgetRepositoryInterface::class);
$this->billRepos = app(BillRepositoryInterface::class);
}
@@ -251,6 +255,8 @@ class RecurrenceTransformer extends AbstractTransformer
$array['budget_name'] = null;
$array['piggy_bank_id'] = null;
$array['piggy_bank_name'] = null;
$array['bill_id'] = null;
$array['bill_name'] = null;
/** @var RecurrenceTransactionMeta $transactionMeta */
foreach ($transaction->recurrenceTransactionMeta as $transactionMeta) {
@@ -258,6 +264,11 @@ class RecurrenceTransformer extends AbstractTransformer
default:
throw new FireflyException(sprintf('Recurrence transformer cant handle field "%s"', $transactionMeta->name));
case 'bill_id':
$bill = $this->billRepos->find((int)$transactionMeta->value);
if (null !== $bill) {
$array['bill_id'] = (string)$bill->id;
$array['bill_name'] = $bill->name;
}
break;
case 'tags':
$array['tags'] = json_decode($transactionMeta->value);

View File

@@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/*
* LiabilityValidation.php
* Copyright (c) 2021 james@firefly-iii.org
@@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Validation\Account;

View File

@@ -0,0 +1,75 @@
<?php
/*
* ValidatesBulkTransactionQuery.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Validation\Api\Data\Bulk;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Validation\Validator;
/**
*
*/
trait ValidatesBulkTransactionQuery
{
/**
* @param Validator $validator
*/
protected function validateTransactionQuery(Validator $validator): void
{
$data = $validator->getData();
// assumption is all validation has already taken place
// and the query key exists.
$json = json_decode($data['query'], true, 8);
if (array_key_exists('source_account_id', $json['where'])
&& array_key_exists('destination_account_id', $json['update'])
) {
// find both accounts
// must be same type.
// already validated: belongs to this user.
$repository = app(AccountRepositoryInterface::class);
$source = $repository->find((int)$json['where']['source_account_id']);
$dest = $repository->find((int)$json['update']['destination_account_id']);
if (null === $source) {
$validator->errors()->add('query', sprintf((string)trans('validation.invalid_query_data'), 'where', 'source_account_id'));
return;
}
if (null === $dest) {
$validator->errors()->add('query', sprintf((string)trans('validation.invalid_query_data'), 'update', 'destination_account_id'));
return;
}
if ($source->accountType->type !== $dest->accountType->type) {
$validator->errors()->add('query', (string)trans('validation.invalid_query_account_type'));
return;
}
// must have same currency:
if($repository->getAccountCurrency($source)->id !== $repository->getAccountCurrency($dest)->id) {
$validator->errors()->add('query', (string)trans('validation.invalid_query_currency'));
}
}
}
}

View File

@@ -28,7 +28,6 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionType;
use FireflyIII\Models\Webhook;
@@ -179,10 +178,13 @@ class FireflyValidator extends Validator
'32', '33', '34', '35',];
// take
$first = substr($value, 0, 4);
$last = substr($value, 4);
$iban = $last . $first;
$iban = str_replace($search, $replace, $iban);
$first = substr($value, 0, 4);
$last = substr($value, 4);
$iban = $last . $first;
$iban = trim(str_replace($search, $replace, $iban));
if (0 === strlen($iban)) {
return false;
}
$checksum = bcmod($iban, '97');
return 1 === (int)$checksum;
@@ -263,16 +265,8 @@ class FireflyValidator extends Validator
if ('set_budget' === $actionType) {
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
$budgets = $repository->getBudgets();
// count budgets, should have at least one
// See reference nr. 102
$count = $budgets->filter(
function (Budget $budget) use ($value) {
return $budget->name === $value;
}
)->count();
return 1 === $count;
return null !== $repository->findByName($value);
}
// if it's link to bill, verify the name of the bill.
@@ -439,7 +433,7 @@ class FireflyValidator extends Validator
*/
private function validateAccountAnonymously(): bool
{
if (!array_key_exists('user_id',$this->data)) {
if (!array_key_exists('user_id', $this->data)) {
return false;
}
@@ -447,16 +441,14 @@ class FireflyValidator extends Validator
$type = AccountType::find($this->data['account_type_id'])->first();
$value = $this->data['name'];
$set = $user->accounts()->where('account_type_id', $type->id)->get();
// See reference nr. 103
/** @var Account $entry */
foreach ($set as $entry) {
if ($entry->name === $value) {
return false;
$set = $user->accounts()->where('account_type_id', $type->id)->get();
$result = $set->first(
function (Account $account) use ($value) {
return $account->name === $value;
}
}
);
return true;
return null === $result;
}
/**
@@ -480,15 +472,13 @@ class FireflyValidator extends Validator
$accountTypeIds = $accountTypes->pluck('id')->toArray();
/** @var Collection $set */
$set = auth()->user()->accounts()->whereIn('account_type_id', $accountTypeIds)->where('id', '!=', $ignore)->get();
// See reference nr. 104
/** @var Account $entry */
foreach ($set as $entry) {
if ($entry->name === $value) {
return false;
$result = $set->first(
function (Account $account) use ($value) {
return $account->name === $value;
}
}
);
return null === $result;
return true;
}
/**
@@ -504,16 +494,13 @@ class FireflyValidator extends Validator
/** @var Collection $set */
$set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
// See reference nr. 105
/** @var Account $entry */
foreach ($set as $entry) {
// See reference nr. 106
if ($entry->name === $value) {
return false;
}
}
return true;
$result = $set->first(
function (Account $account) use ($value) {
return $account->name === $value;
}
);
return null === $result;
}
/**
@@ -718,7 +705,7 @@ class FireflyValidator extends Validator
* @param mixed $value
* @param mixed $parameters
*
* See reference nr. 107
* See reference nr. 107
*
* @return bool
*/
@@ -730,18 +717,8 @@ class FireflyValidator extends Validator
if (null !== $exclude) {
$query->where('piggy_banks.id', '!=', (int)$exclude);
}
$set = $query->get(['piggy_banks.*']);
/** @var PiggyBank $entry */
foreach ($set as $entry) {
$fieldValue = $entry->name;
if ($fieldValue === $value) {
return false;
}
}
return true;
$query->where('piggy_banks.name',$value);
return null === $query->first(['piggy_banks.*']);
}
/**

View File

@@ -8,7 +8,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Added
- A few new pages for the new v2 layout. Thanks @alex6480!
- Feature to be able to rebuild Docker images and show security warnings in new builds.
- Added a new currency yay!
- You can now manage loans and debts a little better.
@@ -16,14 +15,32 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- A better cache routine for layout v2 pages.
- All LDAP libraries have been upgrade.
### Deprecated
- Initial release.
### Removed
- All telemetry options have been removed.
### Fixed
- [Issue 4894](https://github.com/firefly-iii/firefly-iii/issues/4894) Bad number comparison
- Various Sonarqube issues, thanks @hazma-fadil!
- Correct menu display, thanks @vonsogt!
### Security
- Feature to be able to rebuild Docker images and show security warnings in new builds.
### API
- You can disable webhooks with an extra field in API submissions.
- There is a static cron token (see `.env.example`) which is useful for Docker.
## 5.5.13 - 2021-07-25
### Security
- This version of Firefly III fixes [CVE-2021-3663](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3663)
## 5.5.12 - 2021-06-03
⚠️ On July 1st 2021 the Docker tag will change to `fireflyiii/core`. You can already start using the new tag.

View File

@@ -84,18 +84,17 @@
"ext-xml": "*",
"bacon/bacon-qr-code": "2.*",
"diglactic/laravel-breadcrumbs": "^7.0",
"directorytree/ldaprecord-laravel": "^2.2",
"doctrine/dbal": "3.*",
"fideloper/proxy": "4.*",
"gdbots/query-parser": "^2.0",
"guzzlehttp/guzzle": "^7.2",
"jc5/google2fa-laravel": "2.0.5",
"jc5/google2fa-laravel": "2.0.6",
"jc5/recovery": "^2",
"laravel/framework": "^8.48",
"laravel/framework": "^8.51",
"laravel/passport": "10.*",
"laravel/ui": "^3.0",
"laravelcollective/html": "6.*",
"league/commonmark": "1.*",
"league/commonmark": "2.*",
"league/csv": "^9.6",
"league/fractal": "0.*",
"pragmarx/google2fa": "^8.0",
@@ -111,8 +110,8 @@
"filp/whoops": "2.*",
"fakerphp/faker": "1.*",
"mockery/mockery": "1.*",
"nunomaduro/larastan": "^0.7.0",
"phpstan/phpstan": "^0.12.34",
"nunomaduro/larastan": "^0.7.11",
"phpstan/phpstan": "^0.12.94",
"phpstan/phpstan-deprecation-rules": "^0.12.5",
"phpunit/phpunit": "^9.5",
"roave/security-advisories": "dev-master",

1241
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -21,8 +21,6 @@
declare(strict_types=1);
use FireflyIII\Support\Facades\Telemetry;
return [
'name' => envNonEmpty('APP_NAME', 'Firefly III'),
'env' => envNonEmpty('APP_ENV', 'local'),
@@ -143,7 +141,6 @@ return [
'AccountForm' => \FireflyIII\Support\Facades\AccountForm::class,
'PiggyBankForm' => \FireflyIII\Support\Facades\PiggyBankForm::class,
'RuleForm' => \FireflyIII\Support\Facades\RuleForm::class,
'Telemetry' => Telemetry::class,
'Google2FA' => PragmaRX\Google2FALaravel\Facade::class,
'Twig' => TwigBridge\Facade\Twig::class,

15
config/bulk.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
use FireflyIII\Enums\ClauseType;
return [
ClauseType::TRANSACTION => [
ClauseType::WHERE => [
'source_account_id' => 'required|numeric|belongsToUser:accounts,id',
],
ClauseType::UPDATE => [
'destination_account_id' => 'required|numeric|belongsToUser:accounts,id',
],
],
];

View File

@@ -101,7 +101,7 @@ return [
'webhooks' => true,
'handle_debts' => true,
],
'version' => '5.6.0-alpha.1',
'version' => '5.6.0-alpha.2',
'api_version' => '1.5.3',
'db_version' => 17,
@@ -120,7 +120,6 @@ return [
'enable_external_map' => env('ENABLE_EXTERNAL_MAP', false),
'disable_frame_header' => env('DISABLE_FRAME_HEADER', false),
'disable_csp_header' => env('DISABLE_CSP_HEADER', false),
'send_telemetry' => env('SEND_TELEMETRY', false),
'allow_webhooks' => env('ALLOW_WEBHOOKS', false),
// email flags
@@ -134,7 +133,6 @@ return [
'tracker_site_id' => env('TRACKER_SITE_ID', ''),
'tracker_url' => env('TRACKER_URL', ''),
// LDAP and authentication settings
'login_provider' => envNonEmpty('LOGIN_PROVIDER', 'eloquent'),
'authentication_guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'),
@@ -143,9 +141,51 @@ return [
// static config (cannot be changed by user)
'update_endpoint' => 'https://version.firefly-iii.org/index.json',
'telemetry_endpoint' => 'https://telemetry.firefly-iii.org',
'update_minimum_age' => 7,
// enabled languages
'languages' => [
// currently enabled languages
'bg_BG' => ['name_locale' => 'Български', 'name_english' => 'Bulgarian'],
// 'ca_ES' => ['name_locale' => 'Catalan', 'name_english' => 'Catalan'],
'cs_CZ' => ['name_locale' => 'Czech', 'name_english' => 'Czech'],
// 'da_DK' => ['name_locale' => 'Danish', 'name_english' => 'Danish'],
'de_DE' => ['name_locale' => 'Deutsch', 'name_english' => 'German'],
'el_GR' => ['name_locale' => 'Ελληνικά', 'name_english' => 'Greek'],
'en_GB' => ['name_locale' => 'English (GB)', 'name_english' => 'English (GB)'],
'en_US' => ['name_locale' => 'English (US)', 'name_english' => 'English (US)'],
'es_ES' => ['name_locale' => 'Español', 'name_english' => 'Spanish'],
// 'et_EE' => ['name_locale' => 'Estonian', 'name_english' => 'Estonian'],
// 'fa_IR' => ['name_locale' => 'فارسی', 'name_english' => 'Persian'],
'fi_FI' => ['name_locale' => 'Suomi', 'name_english' => 'Finnish'],
'fr_FR' => ['name_locale' => 'Français', 'name_english' => 'French'],
// 'he_IL' => ['name_locale' => 'Hebrew', 'name_english' => 'Hebrew'],
'hu_HU' => ['name_locale' => 'Hungarian', 'name_english' => 'Hungarian'],
// 'id_ID' => ['name_locale' => 'Bahasa Indonesia', 'name_english' => 'Indonesian'],
// 'is_IS' => ['name_locale' => 'Icelandic', 'name_english' => 'Icelandic'],
'it_IT' => ['name_locale' => 'Italiano', 'name_english' => 'Italian'],
'ja_JP' => ['name_locale' => 'Japanese', 'name_english' => 'Japanese'],
// 'lt_LT' => ['name_locale' => 'Lietuvių', 'name_english' => 'Lithuanian'],
'nb_NO' => ['name_locale' => 'Norsk', 'name_english' => 'Norwegian'],
'nl_NL' => ['name_locale' => 'Nederlands', 'name_english' => 'Dutch'],
'pl_PL' => ['name_locale' => 'Polski', 'name_english' => 'Polish '],
'pt_BR' => ['name_locale' => 'Português do Brasil', 'name_english' => 'Portuguese (Brazil)'],
'pt_PT' => ['name_locale' => 'Português', 'name_english' => 'Portuguese'],
'ro_RO' => ['name_locale' => 'Română', 'name_english' => 'Romanian'],
'ru_RU' => ['name_locale' => 'Русский', 'name_english' => 'Russian'],
// 'si_LK' => ['name_locale' => 'සිංහල', 'name_english' => 'Sinhala (Sri Lanka)'],
'sk_SK' => ['name_locale' => 'Slovenčina', 'name_english' => 'Slovak'],
// 'sl_SI' => ['name_locale' => 'Slovenian', 'name_english' => 'Slovenian'],
// 'sr_CS' => ['name_locale' => 'Serbian (Latin)', 'name_english' => 'Serbian (Latin)'],
'sv_SE' => ['name_locale' => 'Svenska', 'name_english' => 'Swedish'],
// 'tlh_AA' => ['name_locale' => 'tlhIngan Hol', 'name_english' => 'Klingon'],
// 'tr_TR' => ['name_locale' => 'Türkçe', 'name_english' => 'Turkish'],
// 'uk_UA' => ['name_locale' => 'Ukranian', 'name_english' => 'Ukranian'],
'vi_VN' => ['name_locale' => 'Tiếng Việt', 'name_english' => 'Vietnamese'],
'zh_TW' => ['name_locale' => 'Chinese Traditional', 'name_english' => 'Chinese Traditional'],
'zh_CN' => ['name_locale' => 'Chinese Simplified', 'name_english' => 'Chinese Simplified'],
],
// web configuration:
'trusted_proxies' => env('TRUSTED_PROXIES', ''),
'layout' => envNonEmpty('FIREFLY_III_LAYOUT', 'v1'),
@@ -157,8 +197,20 @@ return [
'zoom_level' => env('MAP_DEFAULT_ZOOM', '6'),
],
// internal Firefly III configuration:
// edit me = peligro de muerte
// default user-related values
'list_length' => 10, // to be removed if v1 is cancelled.
'default_preferences' => [
'frontPageAccounts' => [],
'listPageSize' => 50,
'currencyPreference' => 'EUR',
'language' => 'en_US',
'locale' => 'equal',
],
'default_currency' => 'EUR',
'default_language' => envNonEmpty('DEFAULT_LANGUAGE', 'en_US'),
'default_locale' => envNonEmpty('DEFAULT_LOCALE', 'equal'),
// "value must be in this list" values
'valid_attachment_models' => [
Account::class,
Bill::class,
@@ -170,7 +222,6 @@ return [
TransactionJournal::class,
Recurrence::class,
],
'allowed_sort_parameters' => ['order', 'name', 'iban'],
'allowedMimes' => [
/* plain files */
'text/plain',
@@ -232,14 +283,16 @@ return [
'application/vnd.oasis.opendocument.database',
'application/vnd.oasis.opendocument.image',
],
'list_length' => 10, // to be removed if v1 is cancelled.
'bill_periods' => ['weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'interest_periods' => ['weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'accountRoles' => ['defaultAsset', 'sharedAsset', 'savingAsset', 'ccAsset', 'cashWalletAsset'],
'valid_liabilities' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE],
'ccTypes' => [
'monthlyFull' => 'Full payment every month',
],
'ccTypes' => ['monthlyFull' => 'Full payment every month',],
'credit_card_types' => ['monthlyFull'],
// "period must be in this list" values
'bill_periods' => ['weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'interest_periods' => ['weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
// settings to translate X to Y
'range_to_repeat_freq' => [
'1D' => 'weekly',
'1W' => 'weekly',
@@ -313,50 +366,6 @@ return [
AccountType::DEBT => AccountType::DEBT,
AccountType::MORTGAGE => AccountType::MORTGAGE,
],
/**
* Languages configuration.
*/
'languages' => [
// currently enabled languages
'bg_BG' => ['name_locale' => 'Български', 'name_english' => 'Bulgarian'],
// 'ca_ES' => ['name_locale' => 'Catalan', 'name_english' => 'Catalan'],
'cs_CZ' => ['name_locale' => 'Czech', 'name_english' => 'Czech'],
// 'da_DK' => ['name_locale' => 'Danish', 'name_english' => 'Danish'],
'de_DE' => ['name_locale' => 'Deutsch', 'name_english' => 'German'],
'el_GR' => ['name_locale' => 'Ελληνικά', 'name_english' => 'Greek'],
'en_GB' => ['name_locale' => 'English (GB)', 'name_english' => 'English (GB)'],
'en_US' => ['name_locale' => 'English (US)', 'name_english' => 'English (US)'],
'es_ES' => ['name_locale' => 'Español', 'name_english' => 'Spanish'],
// 'et_EE' => ['name_locale' => 'Estonian', 'name_english' => 'Estonian'],
// 'fa_IR' => ['name_locale' => 'فارسی', 'name_english' => 'Persian'],
'fi_FI' => ['name_locale' => 'Suomi', 'name_english' => 'Finnish'],
'fr_FR' => ['name_locale' => 'Français', 'name_english' => 'French'],
// 'he_IL' => ['name_locale' => 'Hebrew', 'name_english' => 'Hebrew'],
'hu_HU' => ['name_locale' => 'Hungarian', 'name_english' => 'Hungarian'],
// 'id_ID' => ['name_locale' => 'Bahasa Indonesia', 'name_english' => 'Indonesian'],
// 'is_IS' => ['name_locale' => 'Icelandic', 'name_english' => 'Icelandic'],
'it_IT' => ['name_locale' => 'Italiano', 'name_english' => 'Italian'],
// 'ja_JA' => ['name_locale' => 'Japanese', 'name_english' => 'Japanese'],
// 'lt_LT' => ['name_locale' => 'Lietuvių', 'name_english' => 'Lithuanian'],
'nb_NO' => ['name_locale' => 'Norsk', 'name_english' => 'Norwegian'],
'nl_NL' => ['name_locale' => 'Nederlands', 'name_english' => 'Dutch'],
'pl_PL' => ['name_locale' => 'Polski', 'name_english' => 'Polish '],
'pt_BR' => ['name_locale' => 'Português do Brasil', 'name_english' => 'Portuguese (Brazil)'],
'pt_PT' => ['name_locale' => 'Português', 'name_english' => 'Portuguese'],
'ro_RO' => ['name_locale' => 'Română', 'name_english' => 'Romanian'],
'ru_RU' => ['name_locale' => 'Русский', 'name_english' => 'Russian'],
// 'si_LK' => ['name_locale' => 'සිංහල', 'name_english' => 'Sinhala (Sri Lanka)'],
'sk_SK' => ['name_locale' => 'Slovenčina', 'name_english' => 'Slovak'],
// 'sl_SI' => ['name_locale' => 'Slovenian', 'name_english' => 'Slovenian'],
// 'sr_CS' => ['name_locale' => 'Serbian (Latin)', 'name_english' => 'Serbian (Latin)'],
'sv_SE' => ['name_locale' => 'Svenska', 'name_english' => 'Swedish'],
// 'tlh_AA' => ['name_locale' => 'tlhIngan Hol', 'name_english' => 'Klingon'],
// 'tr_TR' => ['name_locale' => 'Türkçe', 'name_english' => 'Turkish'],
// 'uk_UA' => ['name_locale' => 'Ukranian', 'name_english' => 'Ukranian'],
'vi_VN' => ['name_locale' => 'Tiếng Việt', 'name_english' => 'Vietnamese'],
'zh_TW' => ['name_locale' => 'Chinese Traditional', 'name_english' => 'Chinese Traditional'],
'zh_CN' => ['name_locale' => 'Chinese Simplified', 'name_english' => 'Chinese Simplified'],
],
'transactionTypesByType' => [
'expenses' => ['Withdrawal'],
'withdrawal' => ['Withdrawal'],
@@ -379,8 +388,8 @@ return [
'deposit' => 'fa-long-arrow-right',
'transfer' => 'fa-exchange',
'transfers' => 'fa-exchange',
],
'bindables' => [
// models
'account' => Account::class,
@@ -480,9 +489,7 @@ return [
'limit' => 10,
'range' => 200,
],
'default_currency' => 'EUR',
'default_language' => envNonEmpty('DEFAULT_LANGUAGE', 'en_US'),
'default_locale' => envNonEmpty('DEFAULT_LOCALE', 'equal'),
'search' => [
'operators' => [
@@ -654,14 +661,15 @@ return [
// expected source types for each transaction type, in order of preference.
'expected_source_types' => [
'source' => [
TransactionTypeModel::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
TransactionTypeModel::DEPOSIT => [AccountType::REVENUE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
TransactionTypeModel::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
TransactionTypeModel::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT,
AccountType::MORTGAGE,],
TransactionTypeModel::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET],
TransactionTypeModel::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
TransactionTypeModel::DEPOSIT => [AccountType::REVENUE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
TransactionTypeModel::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
TransactionTypeModel::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT,
AccountType::MORTGAGE,],
TransactionTypeModel::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET],
TransactionTypeModel::LIABILITY_CREDIT => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
// in case no transaction type is known yet, it could be anything.
'none' => [
'none' => [
AccountType::ASSET,
AccountType::EXPENSE,
AccountType::REVENUE,
@@ -890,11 +898,7 @@ return [
'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],
'default_preferences' => [
'frontPageAccounts' => [],
'listPageSize' => 50,
'currencyPreference' => 'EUR',
'language' => 'en_US',
'locale' => 'equal',
],
// only used in v1
'allowed_sort_parameters' => ['order', 'name', 'iban'],
];

View File

@@ -1,29 +1,54 @@
<?php
/*
* 2021_05_09_064644_add_ldap_columns_to_users_table.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddLdapColumnsToUsersTable extends Migration
{
/**
* Run the migrations.
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('domain')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
Schema::table(
'users', function (Blueprint $table) {
$table->dropColumn(['domain']);
});
}
);
}
/**
* Run the migrations.
*/
public function up()
{
Schema::table(
'users', function (Blueprint $table) {
$table->string('domain')->nullable();
}
);
}
}

View File

@@ -1,4 +1,25 @@
<?php
/*
* 2021_05_13_053836_extend_currency_info.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;

View File

@@ -1,7 +1,8 @@
<?php
/*
* StoredTransactionLink.php
* Copyright (c) 2020 james@firefly-iii.org
* 2021_07_05_193044_drop_tele_table.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@@ -21,27 +22,31 @@
declare(strict_types=1);
namespace FireflyIII\Events;
use FireflyIII\Models\TransactionJournalLink;
use Illuminate\Queue\SerializesModels;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Schema;
/**
* Class StoredTransactionLink
* See reference nr. 85
* Class DropTeleTable
*/
class StoredTransactionLink extends Event
class DropTeleTable extends Migration
{
use SerializesModels;
private TransactionJournalLink $link;
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('telemetry');
}
/**
* DestroyedTransactionLink constructor.
* Run the migrations.
*
* @param TransactionJournalLink $link
* @return void
*/
public function __construct(TransactionJournalLink $link)
public function up()
{
$this->link = $link;
Schema::dropIfExists('telemetry');
}
}

View File

@@ -4,6 +4,9 @@
"/public/js/accounts/delete.js": "/public/js/accounts/delete.js",
"/public/js/accounts/show.js": "/public/js/accounts/show.js",
"/public/js/accounts/create.js": "/public/js/accounts/create.js",
"/public/js/accounts/edit.js": "/public/js/accounts/edit.js",
"/public/js/bills/index.js": "/public/js/bills/index.js",
"/public/js/bills/create.js": "/public/js/bills/create.js",
"/public/js/budgets/index.js": "/public/js/budgets/index.js",
"/public/js/transactions/create.js": "/public/js/transactions/create.js",
"/public/js/transactions/edit.js": "/public/js/transactions/edit.js",

View File

@@ -17,16 +17,17 @@
"lodash.clonedeep": "^4.5.0",
"postcss": "^8.1.14",
"resolve-url-loader": "^4.0.0",
"sass": "^1.32.8",
"sass": "^1.37.0",
"sass-loader": "^12.0.0",
"vue-i18n": "^8.24.2",
"vue-loader": "^15.9.5",
"vue-loader": "^15",
"vue-template-compiler": "^2.6.12",
"vuex": "^3.6.2",
"webpack": "^5.40.0"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.3",
"@johmun/vue-tags-input": "^2.1.0",
"admin-lte": "^3.1.0",
"axios-cache-adapter": "^2.7.3",
"bootstrap": "^4.6.0",
@@ -38,8 +39,9 @@
"localforage": "^1.9.0",
"localforage-memoryStorageDriver": "^0.9.2",
"overlayscrollbars": "^1.13.1",
"sortablejs": "^1.13.0",
"v-calendar": "^2.3.0",
"sortablejs": "^1.14.0",
"uiv": "^1.3.1",
"v-calendar": "^2.3.2",
"vue-typeahead-bootstrap": "^2.8.0",
"vue2-leaflet": "^2.7.1"
}

View File

@@ -23,5 +23,4 @@
window.$ = window.jQuery = require('jquery');
// admin stuff
//require('bootstrap');
require('bootstrap');

View File

@@ -34,9 +34,17 @@
<div class="card-body">
<GenericTextInput :disabled="submitting" v-model="name" field-name="name" :errors="errors.name" :title="$t('form.name')"
v-on:set-field="storeField($event)"/>
<Currency :disabled="submitting" v-model="currency_id" :errors="errors.currency" v-on:set-field="storeField($event)"/>
<GenericCurrency :disabled="submitting" v-model="currency_id" :errors="errors.currency_id" v-on:set-field="storeField($event)"/>
<AssetAccountRole :disabled="submitting" v-if="'asset' === type" v-model="account_role" :errors="errors.account_role"
v-on:set-field="storeField($event)"/>
<!-- some CC fields -->
<CreditCardType :disabled="submitting" v-if="'ccAsset' === account_role" v-model="credit_card_type" :errors="errors.credit_card_type"
v-on:set-field="storeField($event)" />
<GenericTextInput :disabled="submitting" v-if="'ccAsset' === account_role" field-type="date" v-model="monthly_payment_date" field-name="monthly_payment_date"
:errors="errors.monthly_payment_date" :title="$t('form.cc_monthly_payment_date')" v-on:set-field="storeField($event)" />
<!-- liability fields -->
<LiabilityType :disabled="submitting" v-if="'liabilities' === type" v-model="liability_type" :errors="errors.liability_type"
v-on:set-field="storeField($event)"/>
<LiabilityDirection :disabled="submitting" v-if="'liabilities' === type" v-model="liability_direction" :errors="errors.liability_direction"
@@ -44,6 +52,7 @@
<GenericTextInput :disabled="submitting" v-if="'liabilities' === type" field-type="number" field-step="any" v-model="liability_amount"
field-name="liability_amount" :errors="errors.liability_amount" :title="$t('form.amount')" v-on:set-field="storeField($event)"/>
<GenericTextInput :disabled="submitting" v-if="'liabilities' === type" field-type="date" v-model="liability_date" field-name="liability_date"
:errors="errors.liability_date" :title="$t('form.date')" v-on:set-field="storeField($event)"/>
@@ -88,7 +97,15 @@
<GenericLocation :disabled="submitting" v-model="location" :title="$t('form.location')" :errors="errors.location"
v-on:set-field="storeField($event)"/>
<GenericAttachments :disabled="submitting" :title="$t('form.attachments')" field-name="attachments" :errors="errors.attachments"/>
<GenericAttachments :disabled="submitting" :title="$t('form.attachments')" field-name="attachments" :errors="errors.attachments"
v-on:selected-attachments="selectedAttachments($event)"
v-on:selected-no-attachments="selectedNoAttachments($event)"
v-on:uploaded-attachments="uploadedAttachments($event)"
:upload-trigger="uploadTrigger"
:upload-object-type="uploadObjectType"
:upload-object-id="uploadObjectId"
/>
</div>
@@ -128,10 +145,13 @@
</template>
<script>
import format from "date-fns/format";
const lodashClonedeep = require('lodash.clonedeep');
import Currency from "./Currency";
import GenericCurrency from "../form/GenericCurrency";
import AssetAccountRole from "./AssetAccountRole"
import LiabilityType from "./LiabilityType";
import CreditCardType from "./CreditCardType";
import LiabilityDirection from "./LiabilityDirection";
import Interest from "./Interest";
import InterestPeriod from "./InterestPeriod";
@@ -145,8 +165,9 @@ import Alert from '../partials/Alert';
export default {
name: "Create",
components: {
Currency, AssetAccountRole, LiabilityType, LiabilityDirection, Interest, InterestPeriod,
GenericTextInput, GenericTextarea, GenericLocation, GenericAttachments, GenericCheckbox, Alert
GenericCurrency, AssetAccountRole, LiabilityType, LiabilityDirection, Interest, InterestPeriod,
GenericTextInput, GenericTextarea, GenericLocation, GenericAttachments, GenericCheckbox, Alert,
CreditCardType
},
created() {
@@ -154,6 +175,9 @@ export default {
let pathName = window.location.pathname;
let parts = pathName.split('/');
this.type = parts[parts.length - 1];
this.date = format(new Date, 'yyyy-MM-dd');
this.monthly_payment_date = format(new Date, 'yyyy-MM-dd');
},
data() {
return {
@@ -178,6 +202,7 @@ export default {
interest: null,
interest_period: 'monthly',
// optional fields
iban: null,
bic: null,
@@ -190,16 +215,31 @@ export default {
notes: null,
location: {},
// credit card fields
monthly_payment_date: null,
credit_card_type: 'monthlyFull',
// has attachments to upload?
hasAttachments: false,
uploadTrigger: false,
uploadObjectId: 0,
uploadObjectType: 'Account',
account_role: 'defaultAsset',
errors: {},
errors: {
currency_id: [],
credit_card_type: [],
},
defaultErrors: {
name: [],
currency: [],
monthly_payment_date: [],
currency_id: [],
account_role: [],
liability_type: [],
liability_direction: [],
liability_amount: [],
credit_card_type: [],
liability_date: [],
interest: [],
interest_period: [],
@@ -228,6 +268,15 @@ export default {
}
this[payload.field] = payload.value;
},
selectedAttachments: function (e) {
this.hasAttachments = true;
},
selectedNoAttachments: function (e) {
this.hasAttachments = false;
},
uploadedAttachments: function (e) {
this.finishSubmission();
},
submitForm: function (e) {
e.preventDefault();
this.submitting = true;
@@ -239,35 +288,16 @@ export default {
axios.post(url, submission)
.then(response => {
this.errors = lodashClonedeep(this.defaultErrors);
// console.log('success!');
this.returnedId = parseInt(response.data.data.id);
this.returnedTitle = response.data.data.attributes.name;
this.successMessage = this.$t('firefly.stored_new_account_js', {ID: this.returnedId, name: this.returnedTitle});
// stay here is false?
if (false === this.createAnother) {
window.location.href = (window.previousURL ?? '/') + '?account_id=' + this.returnedId + '&message=created';
return;
if (this.hasAttachments) {
// upload attachments. Do a callback to a finish up method.
this.uploadObjectId = this.returnedId;
this.uploadTrigger = true;
}
this.submitting = false;
if (this.resetFormAfter) {
// console.log('reset!');
this.name = '';
this.liability_type = 'Loan';
this.liability_direction = 'debit';
this.liability_amount = null;
this.liability_date = null;
this.interest = null;
this.interest_period = 'monthly';
this.iban = null;
this.bic = null;
this.account_number = null;
this.virtual_balance = null;
this.opening_balance = null;
this.opening_balance_date = null;
this.include_net_worth = true;
this.active = true;
this.notes = null;
this.location = {};
if (!this.hasAttachments) {
this.finishSubmission();
}
})
.catch(error => {
@@ -275,6 +305,35 @@ export default {
this.parseErrors(error.response.data);
});
},
finishSubmission: function () {
this.successMessage = this.$t('firefly.stored_new_account_js', {ID: this.returnedId, name: this.returnedTitle});
// stay here is false?
if (false === this.createAnother) {
window.location.href = (window.previousURL ?? '/') + '?account_id=' + this.returnedId + '&message=created';
return;
}
this.submitting = false;
if (this.resetFormAfter) {
// console.log('reset!');
this.name = '';
this.liability_type = 'Loan';
this.liability_direction = 'debit';
this.liability_amount = null;
this.liability_date = null;
this.interest = null;
this.interest_period = 'monthly';
this.iban = null;
this.bic = null;
this.account_number = null;
this.virtual_balance = null;
this.opening_balance = null;
this.opening_balance_date = null;
this.include_net_worth = true;
this.active = true;
this.notes = null;
this.location = {};
}
},
parseErrors: function (errors) {
this.errors = lodashClonedeep(this.defaultErrors);
// console.log(errors);
@@ -282,7 +341,7 @@ export default {
if (errors.errors.hasOwnProperty(i)) {
this.errors[i] = errors.errors[i];
}
if('liability_start_date' === i) {
if ('liability_start_date' === i) {
this.errors.opening_balance_date = errors.errors[i];
}
}
@@ -314,13 +373,13 @@ export default {
submission.opening_balance = this.opening_balance;
submission.opening_balance_date = this.opening_balance_date;
}
if('' === submission.opening_balance) {
if ('' === submission.opening_balance) {
delete submission.opening_balance;
}
if ('asset' === this.type && 'ccAsset' === this.account_role) {
submission.credit_card_type = 'monthlyFull';
submission.monthly_payment_date = '2021-01-01';
submission.credit_card_type = this.credit_card_type;
submission.monthly_payment_date = this.monthly_payment_date;
}
if (Object.keys(this.location).length >= 3) {
submission.longitude = this.location.lng;

View File

@@ -0,0 +1,97 @@
<!--
- LiabilityType.vue
- Copyright (c) 2021 james@firefly-iii.org
-
- This file is part of Firefly III (https://github.com/firefly-iii).
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<template>
<div class="form-group">
<div class="text-xs d-none d-lg-block d-xl-block">
{{ $t('form.cc_type') }}
</div>
<div class="input-group" v-if="loading">
<span class="fas fa-spinner fa-spin"></span>
</div>
<div class="input-group" v-if="!loading">
<select
ref="credit_card_type"
v-model="credit_card_type"
:class="errors.length > 0 ? 'form-control is-invalid' : 'form-control'"
:title="$t('form.cc_type')"
autocomplete="off"
name="credit_card_type"
:disabled=disabled
>
<option v-for="type in this.typeList" :label="type.title" :value="type.slug">{{ type.title }}</option>
</select>
</div>
<span v-if="errors.length > 0">
<span v-for="error in errors" class="text-danger small">{{ error }}<br/></span>
</span>
</div>
</template>
<script>
export default {
name: "CreditCardType",
props: {
value: {},
errors: {},
disabled: {
type: Boolean,
default: false
},
},
data() {
return {
typeList: [],
credit_card_type: this.value,
loading: true
}
},
methods: {
loadRoles: function () {
//
axios.get('./api/v1/configuration/firefly.credit_card_types')
.then(response => {
let content = response.data.data.value;
for (let i in content) {
if (content.hasOwnProperty(i)) {
let current = content[i];
this.typeList.push({slug: current, title: this.$t('firefly.credit_card_type_' + current)})
}
}
this.loading = false;
}
);
}
},
watch: {
credit_card_type: function (value) {
this.$emit('set-field', {field: 'credit_card_type', value: value});
},
value: function(value) {
this.credit_card_type = value;
}
},
created() {
this.loadRoles()
}
}
</script>

Some files were not shown because too many files have changed in this diff Show More