Merge branch 'release/5.5.0-beta.1' into main

This commit is contained in:
James Cole 2021-01-29 18:21:06 +01:00
commit 3ed4d28c4a
532 changed files with 24342 additions and 18125 deletions

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Install composer packages # Install composer packages
composer install --no-suggest --no-scripts --no-ansi composer install --no-scripts --no-ansi
# enable test .env file. # enable test .env file.
cp .ci/.env.ci .env cp .ci/.env.ci .env

View File

@ -52,6 +52,11 @@ LOG_CHANNEL=stack
# nothing will get logged, ever. # nothing will get logged, ever.
APP_LOG_LEVEL=notice APP_LOG_LEVEL=notice
# Audit log level.
# set to "emergency" if you dont want to store audit logs.
# leave on info otherwise.
AUDIT_LOG_LEVEL=info
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
# For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq # For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE # If you use Docker or similar, you can set these variables from a file by appending them with _FILE
@ -271,6 +276,11 @@ TRACKER_URL=
# To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry # To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry
SEND_TELEMETRY=false SEND_TELEMETRY=false
#
# Firefly III supports webhooks. These are security sensitive and must be enabled manually first.
#
ALLOW_WEBHOOKS=false
# You can fine tune the start-up of a Docker container by editing these environment variables. # 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. # 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. # However if you know what you're doing you can significantly speed up container start times.

View File

@ -16,7 +16,12 @@ I am running Firefly III version x.x.x, and my problem is:
<!-- What do you need to do to trigger this bug? --> <!-- What do you need to do to trigger this bug? -->
**Extra info** **Extra info**
<!-- Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom). --> <!-- Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom).
DO NOT PUT ```BACKTICKS``` AROUND THE OUTPUT OF THE /debug PAGE
-->
**Bonus points** **Bonus points**
<!-- Before you submit, verify the following please: --> <!-- Before you submit, verify the following please: -->

27
.github/ISSUE_TEMPLATE/Custom.md vendored Normal file
View File

@ -0,0 +1,27 @@
---
name: I have a question or a problem
about: Ask away!
---
I am running Firefly III version x.x.x.
**Description**
<!-- (if relevant of course) -->
**Extra info**
<!-- Please add extra info here, such as OS, browser, and the output from the `/debug`-page of your Firefly III installation (click the version at the bottom).
DO NOT PUT ```BACKTICKS``` AROUND THE OUTPUT OF THE /debug PAGE
-->
**Bonus points**
<!-- Complete the following checklist for bonus points -->
- I have read the FAQ at https://bit.ly/FF3-FAQ
- I added a screenshot
- I added log files <!-- (see https://bit.ly/FF3-get-debug-info) -->
- I was able to replicate the issue on the demo site.
<!-- - I donated money (this is a joke :wink:)-->

View File

@ -1,15 +1,3 @@
# Welcome to Firefly III on Github! # [Contributing guidelines](https://docs.firefly-iii.org/other-pages/contributing)
:+1::tada: Thank you for taking the time to contribute something to Firefly III! [Contributing guidelines](https://docs.firefly-iii.org/other-pages/contributing)
## Feature requests
I am always interested in expanding Firefly III's many features. Just open a ticket or [drop me a line](mailto:james@firefly-iii.org).
## Pull requests
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `main` branch.
## Translations :us: :fr: :de:
If you see a spelling error, grammatical error or a weird translation in your language, please join [our CrowdIn](https://crowdin.com/project/firefly-iii) project. There, you can submit your translations and fixes. The GitHub repository will download these automatically and they will be included in the next release.

View File

@ -14,7 +14,6 @@ branches:
before_script: before_script:
- phpenv config-rm xdebug.ini || return 0 - phpenv config-rm xdebug.ini || return 0
- composer global require hirak/prestissimo --no-plugins --no-scripts
script: script:
- "./.ci/phpstan.sh" - "./.ci/phpstan.sh"

View File

@ -97,6 +97,7 @@ class AccountController extends Controller
'currency_id' => $currency->id, 'currency_id' => $currency->id,
'currency_name' => $currency->name, 'currency_name' => $currency->name,
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
]; ];
} }
@ -105,11 +106,14 @@ class AccountController extends Controller
$order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE]; $order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE];
usort($return, function ($a, $b) use ($order) { usort(
$return, function ($a, $b) use ($order) {
$pos_a = array_search($a['type'], $order); $pos_a = array_search($a['type'], $order);
$pos_b = array_search($b['type'], $order); $pos_b = array_search($b['type'], $order);
return $pos_a - $pos_b; return $pos_a - $pos_b;
}); }
);
return response()->json($return); return response()->json($return);
} }

View File

@ -24,7 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers; namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\BudgetLimitRequest; use FireflyIII\Api\V1\Requests\BudgetLimitStoreRequest;
use FireflyIII\Api\V1\Requests\BudgetLimitUpdateRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\BudgetLimit;
@ -49,11 +50,8 @@ class BudgetLimitController extends Controller
{ {
use TransactionFilter; use TransactionFilter;
/** @var BudgetLimitRepositoryInterface */ private BudgetLimitRepositoryInterface $blRepository;
private $blRepository; private BudgetRepositoryInterface $repository;
/** @var BudgetRepositoryInterface The budget repository */
private $repository;
/** /**
@ -104,6 +102,7 @@ class BudgetLimitController extends Controller
public function index(Request $request): JsonResponse public function index(Request $request): JsonResponse
{ {
$manager = $this->getManager(); $manager = $this->getManager();
$manager->parseIncludes('budget');
$budgetId = (int)($request->get('budget_id') ?? 0); $budgetId = (int)($request->get('budget_id') ?? 0);
$budget = $this->repository->findNull($budgetId); $budget = $this->repository->findNull($budgetId);
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
@ -156,13 +155,13 @@ class BudgetLimitController extends Controller
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param BudgetLimitRequest $request * @param BudgetLimitStoreRequest $request
* *
* @return JsonResponse * @return JsonResponse
* @throws FireflyException * @throws FireflyException
* *
*/ */
public function store(BudgetLimitRequest $request): JsonResponse public function store(BudgetLimitStoreRequest $request): JsonResponse
{ {
$data = $request->getAll(); $data = $request->getAll();
$data['start_date'] = $data['start']; $data['start_date'] = $data['start'];
@ -237,12 +236,12 @@ class BudgetLimitController extends Controller
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
* *
* @param BudgetLimitRequest $request * @param BudgetLimitUpdateRequest $request
* @param BudgetLimit $budgetLimit * @param BudgetLimit $budgetLimit
* *
* @return JsonResponse * @return JsonResponse
*/ */
public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse public function update(BudgetLimitUpdateRequest $request, BudgetLimit $budgetLimit): JsonResponse
{ {
$data = $request->getAll(); $data = $request->getAll();
$budgetLimit = $this->blRepository->update($budgetLimit, $data); $budgetLimit = $this->blRepository->update($budgetLimit, $data);

View File

@ -149,7 +149,7 @@ class AccountController extends Controller
foreach ($tempData as $entry) { foreach ($tempData as $entry) {
$currencyId = $entry['currency_id']; $currencyId = $entry['currency_id'];
$name = $entry['name']; $name = $entry['name'];
$chartData[$currencyId]['entries'][$name] = round($entry['difference'], $chartData[$currencyId]['currency_decimal_places']); $chartData[$currencyId]['entries'][$name] = round((float) $entry['difference'], $chartData[$currencyId]['currency_decimal_places']);
} }
$chartData = array_values($chartData); $chartData = array_values($chartData);
@ -206,11 +206,11 @@ class AccountController extends Controller
/** @var Carbon $currentStart */ /** @var Carbon $currentStart */
$currentStart = clone $start; $currentStart = clone $start;
$range = app('steam')->balanceInRange($account, $start, clone $end); $range = app('steam')->balanceInRange($account, $start, clone $end);
$previous = round(array_values($range)[0], 12); $previous = round((float) array_values($range)[0], 12);
while ($currentStart <= $end) { while ($currentStart <= $end) {
$format = $currentStart->format('Y-m-d'); $format = $currentStart->format('Y-m-d');
$label = $currentStart->format('Y-m-d'); $label = $currentStart->format('Y-m-d');
$balance = array_key_exists($format, $range) ? round($range[$format], 12) : $previous; $balance = array_key_exists($format, $range) ? round((float) $range[$format], 12) : $previous;
$previous = $balance; $previous = $balance;
$currentStart->addDay(); $currentStart->addDay();
$currentSet['entries'][$label] = $balance; $currentSet['entries'][$label] = $balance;
@ -300,7 +300,7 @@ class AccountController extends Controller
foreach ($tempData as $entry) { foreach ($tempData as $entry) {
$currencyId = $entry['currency_id']; $currencyId = $entry['currency_id'];
$name = $entry['name']; $name = $entry['name'];
$chartData[$currencyId]['entries'][$name] = round($entry['difference'], $chartData[$currencyId]['currency_decimal_places']); $chartData[$currencyId]['entries'][$name] = round((float) $entry['difference'], $chartData[$currencyId]['currency_decimal_places']);
} }
$chartData = array_values($chartData); $chartData = array_values($chartData);

View File

@ -105,7 +105,7 @@ class AvailableBudgetController extends Controller
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'type' => 'line', // line, area or bar 'type' => 'line', // line, area or bar
'yAxisID' => 0, // 0, 1, 2 'yAxisID' => 0, // 0, 1, 2
'entries' => [round($left, $currency->decimal_places)], 'entries' => [round((float) $left, $currency->decimal_places)],
], ],
]; ];

View File

@ -23,7 +23,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers; namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\CurrencyRequest; use FireflyIII\Api\V1\Requests\CurrencyUpdateRequest;
use FireflyIII\Api\V1\Requests\CurrencyStoreRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
@ -580,12 +581,12 @@ class CurrencyController extends Controller
/** /**
* Store new currency. * Store new currency.
* *
* @param CurrencyRequest $request * @param CurrencyStoreRequest $request
* *
* @return JsonResponse * @return JsonResponse
* @throws FireflyException * @throws FireflyException
*/ */
public function store(CurrencyRequest $request): JsonResponse public function store(CurrencyStoreRequest $request): JsonResponse
{ {
$currency = $this->repository->store($request->getAll()); $currency = $this->repository->store($request->getAll());
if (true === $request->boolean('default')) { if (true === $request->boolean('default')) {
@ -664,12 +665,12 @@ class CurrencyController extends Controller
/** /**
* Update a currency. * Update a currency.
* *
* @param CurrencyRequest $request * @param CurrencyUpdateRequest $request
* @param TransactionCurrency $currency * @param TransactionCurrency $currency
* *
* @return JsonResponse * @return JsonResponse
*/ */
public function update(CurrencyRequest $request, TransactionCurrency $currency): JsonResponse public function update(CurrencyUpdateRequest $request, TransactionCurrency $currency): JsonResponse
{ {
$data = $request->getAll(); $data = $request->getAll();
$currency = $this->repository->update($currency, $data); $currency = $this->repository->update($currency, $data);

View File

@ -1,112 +0,0 @@
<?php
/**
* CurrencyExchangeRateController.php
* Copyright (c) 2019 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;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Services\Currency\ExchangeRateInterface;
use FireflyIII\Transformers\CurrencyExchangeRateTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use League\Fractal\Resource\Item;
/**
* Class CurrencyExchangeRateController
*
* @codeCoverageIgnore
*/
class CurrencyExchangeRateController extends Controller
{
/** @var CurrencyRepositoryInterface The currency repository */
private $repository;
/**
* CurrencyExchangeRateController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $admin */
$admin = auth()->user();
$this->repository = app(CurrencyRepositoryInterface::class);
$this->repository->setUser($admin);
return $next($request);
}
);
}
/**
* Show an exchange rate.
*
* @param Request $request
*
* @return JsonResponse
* @throws FireflyException
*/
public function index(Request $request): JsonResponse
{
$manager = $this->getManager();
$fromCurrency = $this->repository->findByCodeNull($request->get('from') ?? 'EUR');
$toCurrency = $this->repository->findByCodeNull($request->get('to') ?? 'USD');
if (null === $fromCurrency) {
throw new FireflyException('200007: Unknown source currency');
}
if (null === $toCurrency) {
throw new FireflyException('200007: Unknown destination currency');
}
/** @var Carbon $dateObj */
$dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d'));
$this->parameters->set('from', $fromCurrency->code);
$this->parameters->set('to', $toCurrency->code);
$this->parameters->set('date', $dateObj->format('Y-m-d'));
$this->parameters->set('amount', $request->get('amount'));
$rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj);
if (null === $rate) {
/** @var User $admin */
$admin = auth()->user();
// create service:
/** @var ExchangeRateInterface $service */
$service = app(ExchangeRateInterface::class);
$service->setUser($admin);
$rate = $service->getRate($fromCurrency, $toCurrency, $dateObj);
}
/** @var CurrencyExchangeRateTransformer $transformer */
$transformer = app(CurrencyExchangeRateTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($rate, $transformer, 'currency_exchange_rates');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@ -0,0 +1,131 @@
<?php
declare(strict_types=1);
/*
* DateController.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/>.
*/
namespace FireflyIII\Api\V1\Controllers\Insight\Expense;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\ApiSupport;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class DateController
*
* Shows expense information grouped or limited by date.
* Ie. all expenses grouped by account + currency.
*/
class DateController extends Controller
{
use ApiSupport;
private CurrencyRepositoryInterface $currencyRepository;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser($user);
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
$this->currencyRepository->setUser($user);
return $next($request);
}
);
}
/**
*
*/
public function basic(DateRequest $request): JsonResponse
{
// parameters for chart:
$dates = $request->getAll();
/** @var Carbon $start */
$start = $dates['start'];
/** @var Carbon $end */
$end = $dates['end'];
$start->subDay();
// prep some vars:
$currencies = [];
$chartData = [];
$tempData = [];
// grab all accounts and names
$accounts = $this->repository->getAccountsByType([AccountType::EXPENSE]);
$accountNames = $this->extractNames($accounts);
$startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start);
$endBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $end);
// loop the end balances. This is an array for each account ($expenses)
foreach ($endBalances as $accountId => $expenses) {
$accountId = (int)$accountId;
// loop each expense entry (each entry can be a different currency).
foreach ($expenses as $currencyId => $endAmount) {
$currencyId = (int)$currencyId;
// see if there is an accompanying start amount.
// grab the difference and find the currency.
$startAmount = $startBalances[$accountId][$currencyId] ?? '0';
$diff = bcsub($endAmount, $startAmount);
$currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId);
if (0 !== bccomp($diff, '0')) {
// store the values in a temporary array.
$tempData[] = [
'id' => $accountId,
'name' => $accountNames[$accountId],
'difference' => bcmul($diff, '-1'),
'difference_float' => ((float)$diff) * -1,
'currency_id' => $currencyId,
'currency_code' => $currencies[$currencyId]->code,
];
}
}
}
// sort temp array by amount.
$amounts = array_column($tempData, 'difference_float');
array_multisort($amounts, SORT_ASC, $tempData);
return response()->json($tempData);
}
}

View File

@ -0,0 +1,131 @@
<?php
declare(strict_types=1);
/*
* DateController.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/>.
*/
namespace FireflyIII\Api\V1\Controllers\Insight\Income;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\ApiSupport;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class DateController
*
* Shows income information grouped or limited by date.
* Ie. all income grouped by revenue + currency.
*/
class DateController extends Controller
{
use ApiSupport;
private CurrencyRepositoryInterface $currencyRepository;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser($user);
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
$this->currencyRepository->setUser($user);
return $next($request);
}
);
}
/**
*
*/
public function basic(DateRequest $request): JsonResponse
{
// parameters for chart:
$dates = $request->getAll();
/** @var Carbon $start */
$start = $dates['start'];
/** @var Carbon $end */
$end = $dates['end'];
$start->subDay();
// prep some vars:
$currencies = [];
$chartData = [];
$tempData = [];
// grab all accounts and names
$accounts = $this->repository->getAccountsByType([AccountType::REVENUE]);
$accountNames = $this->extractNames($accounts);
$startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start);
$endBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $end);
// loop the end balances. This is an array for each account ($expenses)
foreach ($endBalances as $accountId => $expenses) {
$accountId = (int)$accountId;
// loop each expense entry (each entry can be a different currency).
foreach ($expenses as $currencyId => $endAmount) {
$currencyId = (int)$currencyId;
// see if there is an accompanying start amount.
// grab the difference and find the currency.
$startAmount = $startBalances[$accountId][$currencyId] ?? '0';
$diff = bcsub($endAmount, $startAmount);
$currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId);
if (0 !== bccomp($diff, '0')) {
// store the values in a temporary array.
$tempData[] = [
'id' => $accountId,
'name' => $accountNames[$accountId],
'difference' => $diff,
'difference_float' => (float)$diff,
'currency_id' => $currencyId,
'currency_code' => $currencies[$currencyId]->code,
];
}
}
}
// sort temp array by amount.
$amounts = array_column($tempData, 'difference_float');
array_multisort($amounts, SORT_ASC, $tempData);
return response()->json($tempData);
}
}

View File

@ -23,7 +23,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers; namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\LinkTypeRequest; use FireflyIII\Api\V1\Requests\LinkTypeStoreRequest;
use FireflyIII\Api\V1\Requests\LinkTypeUpdateRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\LinkType; use FireflyIII\Models\LinkType;
@ -150,12 +151,12 @@ class LinkTypeController extends Controller
/** /**
* Store new object. * Store new object.
* *
* @param LinkTypeRequest $request * @param LinkTypeStoreRequest $request
* *
* @return JsonResponse * @return JsonResponse
* @throws FireflyException * @throws FireflyException
*/ */
public function store(LinkTypeRequest $request): JsonResponse public function store(LinkTypeStoreRequest $request): JsonResponse
{ {
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
@ -239,13 +240,13 @@ class LinkTypeController extends Controller
/** /**
* Update object. * Update object.
* *
* @param LinkTypeRequest $request * @param LinkTypeUpdateRequest $request
* @param LinkType $linkType * @param LinkType $linkType
* *
* @return JsonResponse * @return JsonResponse
* @throws FireflyException * @throws FireflyException
*/ */
public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse public function update(LinkTypeUpdateRequest $request, LinkType $linkType): JsonResponse
{ {
if (false === $linkType->editable) { if (false === $linkType->editable) {
throw new FireflyException('200020: Link type cannot be changed.'); throw new FireflyException('200020: Link type cannot be changed.');

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers; namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\PiggyBankRequest; use FireflyIII\Api\V1\Requests\PiggyBankUpdateRequest;
use FireflyIII\Api\V1\Requests\PiggyBankStoreRequest; use FireflyIII\Api\V1\Requests\PiggyBankStoreRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
@ -224,12 +224,12 @@ class PiggyBankController extends Controller
/** /**
* Update piggy bank. * Update piggy bank.
* *
* @param PiggyBankRequest $request * @param PiggyBankUpdateRequest $request
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
* @return JsonResponse * @return JsonResponse
*/ */
public function update(PiggyBankRequest $request, PiggyBank $piggyBank): JsonResponse public function update(PiggyBankUpdateRequest $request, PiggyBank $piggyBank): JsonResponse
{ {
$data = $request->getAll(); $data = $request->getAll();
$piggyBank = $this->repository->update($piggyBank, $data); $piggyBank = $this->repository->update($piggyBank, $data);

View File

@ -0,0 +1,99 @@
<?php
/*
* IndexController.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/>.
*/
namespace FireflyIII\Api\V1\Controllers\Preferences;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Support\Facades\Navigation;
use Illuminate\Http\JsonResponse;
/**
* Class IndexController
*/
class IndexController extends Controller
{
public const DATE_FORMAT = 'Y-m-d';
/**
* Return users preferred date range settings, the current period
* and some previous / next periods.
*
* @return JsonResponse
*/
public function dateRanges(): JsonResponse
{
$range = app('preferences')->get('viewRange', '1M')->data;
$return = [
'range' => $range,
'ranges' => [],
'default' => null,
];
$today = Carbon::today(config('app.timezone'));
$start = Navigation::startOfPeriod($today, $range);
$todayStr = $today->format(self::DATE_FORMAT);
// optional date ranges. Maybe to be configured later
// current $period
$title = (string)Navigation::periodShow($start, $range);
$return['default'] = $title;
$return['ranges'][$title] = [$start->format(self::DATE_FORMAT),
Navigation::endOfPeriod($start, $range)->format(self::DATE_FORMAT)];
// previous $period
$previousStart = Navigation::subtractPeriod($start, $range);
$title = (string)Navigation::periodShow($previousStart, $range);
$return['ranges'][$title] = [$previousStart->format(self::DATE_FORMAT),
Navigation::endOfPeriod($previousStart, $range)->format(self::DATE_FORMAT)];
// next $period
$nextStart = Navigation::addPeriod($start, $range, 0);
$title = (string)Navigation::periodShow($nextStart, $range);
$return['ranges'][$title] = [$nextStart->format(self::DATE_FORMAT),
Navigation::endOfPeriod($nextStart, $range)->format(self::DATE_FORMAT)];
// --
// last seven days:
$seven = Carbon::today()->subDays(7);
$title = (string)trans('firefly.last_seven_days');
$return['ranges'][$title] = [$seven->format(self::DATE_FORMAT), $todayStr];
// last 30 days:
$thirty = Carbon::today()->subDays(30);
$title = (string)trans('firefly.last_thirty_days');
$return['ranges'][$title] = [$thirty->format(self::DATE_FORMAT), $todayStr];
// last 180 days
$long = Carbon::today()->subDays(180);
$title = (string)trans('firefly.last_180_days');
$return['ranges'][$title] = [$long->format(self::DATE_FORMAT), $todayStr];
// YTD
$YTD = Carbon::today()->startOfYear();
$title = (string)trans('firefly.YTD');
$return['ranges'][$title] = [$YTD->format(self::DATE_FORMAT), $todayStr];
// ---
// everything
$repository = app(JournalRepositoryInterface::class);
$journal = $repository->firstNull();
$first = null === $journal ? clone $YTD : clone $journal->date;
$title = (string)trans('firefly.everything');
$return['ranges'][$title] = [$first->format(self::DATE_FORMAT), $todayStr];
return response()->json($return);
}
}

View File

@ -24,7 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers; namespace FireflyIII\Api\V1\Controllers;
use Exception; use Exception;
use FireflyIII\Api\V1\Requests\RuleGroupRequest; use FireflyIII\Api\V1\Requests\RuleGroupUpdateRequest;
use FireflyIII\Api\V1\Requests\RuleGroupStoreRequest;
use FireflyIII\Api\V1\Requests\RuleGroupTestRequest; use FireflyIII\Api\V1\Requests\RuleGroupTestRequest;
use FireflyIII\Api\V1\Requests\RuleGroupTriggerRequest; use FireflyIII\Api\V1\Requests\RuleGroupTriggerRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
@ -221,11 +222,11 @@ class RuleGroupController extends Controller
/** /**
* Store new object. * Store new object.
* *
* @param RuleGroupRequest $request * @param RuleGroupStoreRequest $request
* *
* @return JsonResponse * @return JsonResponse
*/ */
public function store(RuleGroupRequest $request): JsonResponse public function store(RuleGroupStoreRequest $request): JsonResponse
{ {
$ruleGroup = $this->ruleGroupRepository->store($request->getAll()); $ruleGroup = $this->ruleGroupRepository->store($request->getAll());
$manager = $this->getManager(); $manager = $this->getManager();
@ -341,12 +342,12 @@ class RuleGroupController extends Controller
/** /**
* Update a rule group. * Update a rule group.
* *
* @param RuleGroupRequest $request * @param RuleGroupUpdateRequest $request
* @param RuleGroup $ruleGroup * @param RuleGroup $ruleGroup
* *
* @return JsonResponse * @return JsonResponse
*/ */
public function update(RuleGroupRequest $request, RuleGroup $ruleGroup): JsonResponse public function update(RuleGroupUpdateRequest $request, RuleGroup $ruleGroup): JsonResponse
{ {
$ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll()); $ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll());
$manager = $this->getManager(); $manager = $this->getManager();

View File

@ -48,10 +48,11 @@ class TransactionController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
$fullQuery = (string)$request->get('query'); $fullQuery = (string)$request->get('query');
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$pageSize = 0 === (int)$request->get('limit') ? $pageSize : (int)$request->get('limit');
$searcher->parseQuery($fullQuery); $searcher->parseQuery($fullQuery);
$searcher->setPage($page); $searcher->setPage($page);
$searcher->setLimit((int) config('firefly.search_result_limit')); $searcher->setLimit($pageSize);
$groups = $searcher->searchTransactions(); $groups = $searcher->searchTransactions();
$parameters = ['search' => $fullQuery]; $parameters = ['search' => $fullQuery];
$url = route('api.v1.search.transactions') . '?' . http_build_query($parameters); $url = route('api.v1.search.transactions') . '?' . http_build_query($parameters);

View File

@ -47,24 +47,12 @@ use Illuminate\Http\JsonResponse;
*/ */
class SummaryController extends Controller class SummaryController extends Controller
{ {
/** @var AvailableBudgetRepositoryInterface */ private AvailableBudgetRepositoryInterface $abRepository;
private $abRepository; private AccountRepositoryInterface $accountRepository;
private BillRepositoryInterface $billRepository;
/** @var AccountRepositoryInterface */ private BudgetRepositoryInterface $budgetRepository;
private $accountRepository; private CurrencyRepositoryInterface $currencyRepos;
private OperationsRepositoryInterface $opsRepository;
/** @var BillRepositoryInterface */
private $billRepository;
/** @var BudgetRepositoryInterface */
private $budgetRepository;
/** @var CurrencyRepositoryInterface */
private $currencyRepos;
/** @var OperationsRepositoryInterface */
private $opsRepository;
/** /**
* SummaryController constructor. * SummaryController constructor.
@ -197,7 +185,7 @@ class SummaryController extends Controller
$return[] = [ $return[] = [
'key' => sprintf('balance-in-%s', $currency->code), 'key' => sprintf('balance-in-%s', $currency->code),
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]), 'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => round($sums[$currencyId] ?? 0, $currency->decimal_places), 'monetary_value' => round((float) $sums[$currencyId] ?? 0, $currency->decimal_places),
'currency_id' => $currency->id, 'currency_id' => $currency->id,
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
@ -210,7 +198,7 @@ class SummaryController extends Controller
$return[] = [ $return[] = [
'key' => sprintf('spent-in-%s', $currency->code), 'key' => sprintf('spent-in-%s', $currency->code),
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]), 'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => round($expenses[$currencyId] ?? 0, $currency->decimal_places), 'monetary_value' => round((float) ($expenses[$currencyId] ?? 0), $currency->decimal_places),
'currency_id' => $currency->id, 'currency_id' => $currency->id,
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
@ -222,7 +210,7 @@ class SummaryController extends Controller
$return[] = [ $return[] = [
'key' => sprintf('earned-in-%s', $currency->code), 'key' => sprintf('earned-in-%s', $currency->code),
'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]), 'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => round($incomes[$currencyId] ?? 0, $currency->decimal_places), 'monetary_value' => round((float) ($incomes[$currencyId] ?? 0), $currency->decimal_places),
'currency_id' => $currency->id, 'currency_id' => $currency->id,
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
@ -260,7 +248,7 @@ class SummaryController extends Controller
$return[] = [ $return[] = [
'key' => sprintf('bills-paid-in-%s', $currency->code), 'key' => sprintf('bills-paid-in-%s', $currency->code),
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]), 'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => round($amount, $currency->decimal_places), 'monetary_value' => round((float) $amount, $currency->decimal_places),
'currency_id' => $currency->id, 'currency_id' => $currency->id,
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
@ -280,7 +268,7 @@ class SummaryController extends Controller
$return[] = [ $return[] = [
'key' => sprintf('bills-unpaid-in-%s', $currency->code), 'key' => sprintf('bills-unpaid-in-%s', $currency->code),
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $currency->symbol]), 'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => round($amount, $currency->decimal_places), 'monetary_value' => round((float) $amount, $currency->decimal_places),
'currency_id' => $currency->id, 'currency_id' => $currency->id,
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
@ -324,7 +312,7 @@ class SummaryController extends Controller
$return[] = [ $return[] = [
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']), 'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]), 'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
'monetary_value' => round($leftToSpend, $row['currency_decimal_places']), 'monetary_value' => round((float) $leftToSpend, $row['currency_decimal_places']),
'currency_id' => $row['currency_id'], 'currency_id' => $row['currency_id'],
'currency_code' => $row['currency_code'], 'currency_code' => $row['currency_code'],
'currency_symbol' => $row['currency_symbol'], 'currency_symbol' => $row['currency_symbol'],
@ -384,7 +372,7 @@ class SummaryController extends Controller
foreach ($netWorthSet as $data) { foreach ($netWorthSet as $data) {
/** @var TransactionCurrency $currency */ /** @var TransactionCurrency $currency */
$currency = $data['currency']; $currency = $data['currency'];
$amount = round($data['balance'], $currency->decimal_places); $amount = round((float) $data['balance'], $currency->decimal_places);
if (0.0 === $amount) { if (0.0 === $amount) {
continue; continue;
} }

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\TransactionStoreRequest; use FireflyIII\Api\V1\Requests\TransactionStoreRequest;
use FireflyIII\Api\V1\Requests\TransactionUpdateRequest; use FireflyIII\Api\V1\Requests\TransactionUpdateRequest;
use FireflyIII\Events\DestroyedTransactionGroup;
use FireflyIII\Events\StoredTransactionGroup; use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Events\UpdatedTransactionGroup; use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\DuplicateTransactionException;
@ -36,6 +37,7 @@ use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface; use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Rules\IsDuplicateTransaction;
use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\AttachmentTransformer; use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\PiggyBankEventTransformer; use FireflyIII\Transformers\PiggyBankEventTransformer;
@ -45,11 +47,13 @@ use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Validation\ValidationException;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
use Log; use Log;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Validator;
/** /**
* Class TransactionController * Class TransactionController
@ -142,6 +146,8 @@ class TransactionController extends Controller
public function delete(TransactionGroup $transactionGroup): JsonResponse public function delete(TransactionGroup $transactionGroup): JsonResponse
{ {
$this->repository->destroyGroup($transactionGroup); $this->repository->destroyGroup($transactionGroup);
// trigger just after destruction
event(new DestroyedTransactionGroup($transactionGroup));
return response()->json([], 204); return response()->json([], 204);
} }
@ -289,7 +295,7 @@ class TransactionController extends Controller
* @param TransactionStoreRequest $request * @param TransactionStoreRequest $request
* *
* @return JsonResponse * @return JsonResponse
* @throws FireflyException * @throws FireflyException|ValidationException
*/ */
public function store(TransactionStoreRequest $request): JsonResponse public function store(TransactionStoreRequest $request): JsonResponse
{ {
@ -304,29 +310,16 @@ class TransactionController extends Controller
$transactionGroup = $this->groupRepository->store($data); $transactionGroup = $this->groupRepository->store($data);
} catch (DuplicateTransactionException $e) { } catch (DuplicateTransactionException $e) {
Log::warning('Caught a duplicate transaction. Return error message.'); Log::warning('Caught a duplicate transaction. Return error message.');
// return bad validation message. $validator = Validator::make(
// TODO use Laravel's internal validation thing to do this. ['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction]
$response = [ );
'message' => 'The given data was invalid.', throw new ValidationException($validator);
'errors' => [
'transactions.0.description' => [$e->getMessage()],
],
];
return response()->json($response, 422);
} catch (FireflyException $e) { } catch (FireflyException $e) {
Log::warning('Caught an exception. Return error message.'); Log::warning('Caught an exception. Return error message.');
Log::error($e->getMessage()); Log::error($e->getMessage());
// return bad validation message. $message = sprintf('Internal exception: %s', $e->getMessage());
// TODO use Laravel's internal validation thing to do this. $validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction]);
$response = [ throw new ValidationException($validator);
'message' => 'The given data was invalid.',
'errors' => [
'transactions.0.description' => [sprintf('Internal exception: %s', $e->getMessage())],
],
];
return response()->json($response, 422);
} }
app('preferences')->mark(); app('preferences')->mark();
event(new StoredTransactionGroup($transactionGroup, $data['apply_rules'] ?? true)); event(new StoredTransactionGroup($transactionGroup, $data['apply_rules'] ?? true));

View File

@ -0,0 +1,80 @@
<?php
declare(strict_types=1);
/*
* CreateController.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/>.
*/
namespace FireflyIII\Api\V1\Controllers\Webhook;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Webhook\CreateRequest;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Transformers\WebhookTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item;
/**
* Class CreateController
*/
class CreateController extends Controller
{
private WebhookRepositoryInterface $repository;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $admin */
$admin = auth()->user();
/** @var WebhookRepositoryInterface repository */
$this->repository = app(WebhookRepositoryInterface::class);
$this->repository->setUser($admin);
return $next($request);
}
);
}
/**
* @param CreateRequest $request
*
* @return JsonResponse
*/
public function store(CreateRequest $request): JsonResponse
{
$data = $request->getData();
$webhook = $this->repository->store($data);
$manager = $this->getManager();
/** @var WebhookTransformer $transformer */
$transformer = app(WebhookTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($webhook, $transformer, 'webhooks');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
/*
* DeleteController.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/>.
*/
namespace FireflyIII\Api\V1\Controllers\Webhook;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\Webhook;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class DeleteController
*/
class DeleteController extends Controller
{
private WebhookRepositoryInterface $repository;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $admin */
$admin = auth()->user();
/** @var WebhookRepositoryInterface repository */
$this->repository = app(WebhookRepositoryInterface::class);
$this->repository->setUser($admin);
return $next($request);
}
);
}
/**
* Remove the specified resource from storage.
*
* @param Webhook $webhook
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function destroy(Webhook $webhook): JsonResponse
{
$this->repository->destroy($webhook);
return response()->json([], 204);
}
}

View File

@ -0,0 +1,81 @@
<?php
declare(strict_types=1);
/*
* EditController.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/>.
*/
namespace FireflyIII\Api\V1\Controllers\Webhook;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Webhook\UpdateRequest;
use FireflyIII\Models\Webhook;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Transformers\WebhookTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item;
/**
* Class EditController
*/
class EditController extends Controller
{
private WebhookRepositoryInterface $repository;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $admin */
$admin = auth()->user();
/** @var WebhookRepositoryInterface repository */
$this->repository = app(WebhookRepositoryInterface::class);
$this->repository->setUser($admin);
return $next($request);
}
);
}
/**
* @param Webhook $webhook
* @param UpdateRequest $request
*
* @return JsonResponse
*/
public function update(Webhook $webhook, UpdateRequest $request): JsonResponse
{
$data = $request->getData();
$webhook = $this->repository->update($webhook, $data);
$manager = $this->getManager();
/** @var WebhookTransformer $transformer */
$transformer = app(WebhookTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($webhook, $transformer, 'webhooks');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@ -0,0 +1,88 @@
<?php
declare(strict_types=1);
/*
* IndexController.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/>.
*/
namespace FireflyIII\Api\V1\Controllers\Webhook;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Transformers\WebhookTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
/**
* Class IndexController
*/
class IndexController extends Controller
{
private WebhookRepositoryInterface $repository;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $admin */
$admin = auth()->user();
/** @var WebhookRepositoryInterface repository */
$this->repository = app(WebhookRepositoryInterface::class);
$this->repository->setUser($admin);
return $next($request);
}
);
}
/**
* Display a listing of the resource.
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function index(): JsonResponse
{
$webhooks = $this->repository->all();
$manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$count = $webhooks->count();
$bills = $webhooks->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($webhooks, $count, $pageSize, $this->parameters->get('page'));
/** @var WebhookTransformer $transformer */
$transformer = app(WebhookTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($bills, $transformer, 'webhooks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@ -26,7 +26,10 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Location; use FireflyIII\Models\Location;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\UniqueAccountNumber;
use FireflyIII\Rules\UniqueIban;
use FireflyIII\Support\Request\AppendsLocationData; use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -37,18 +40,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class AccountStoreRequest extends FormRequest class AccountStoreRequest extends FormRequest
{ {
use ConvertsDataTypes, AppendsLocationData; use ConvertsDataTypes, AppendsLocationData, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* @return array * @return array
@ -108,12 +100,13 @@ class AccountStoreRequest extends FormRequest
$accountRoles = implode(',', config('firefly.accountRoles')); $accountRoles = implode(',', config('firefly.accountRoles'));
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); $types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$type = $this->string('type');
$rules = [ $rules = [
'name' => 'required|min:1|uniqueAccountForUser', 'name' => 'required|min:1|uniqueAccountForUser',
'type' => 'required|' . sprintf('in:%s', $types), 'type' => 'required|' . sprintf('in:%s', $types),
'iban' => 'iban|nullable', 'iban' => ['iban', 'nullable', new UniqueIban(null, $type)],
'bic' => 'bic|nullable', 'bic' => 'bic|nullable',
'account_number' => 'between:1,255|nullable|uniqueAccountNumberForUser', 'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber(null, $type)],
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable', 'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
'opening_balance_date' => 'date|required_with:opening_balance|nullable', 'opening_balance_date' => 'date|required_with:opening_balance|nullable',
'virtual_balance' => 'numeric|nullable', 'virtual_balance' => 'numeric|nullable',
@ -132,6 +125,7 @@ class AccountStoreRequest extends FormRequest
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly', 'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',
'notes' => 'min:0|max:65536', 'notes' => 'min:0|max:65536',
]; ];
return Location::requestRules($rules); return Location::requestRules($rules);
} }
} }

View File

@ -26,7 +26,10 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Location; use FireflyIII\Models\Location;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\UniqueAccountNumber;
use FireflyIII\Rules\UniqueIban;
use FireflyIII\Support\Request\AppendsLocationData; use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -37,18 +40,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class AccountUpdateRequest extends FormRequest class AccountUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes, AppendsLocationData; use ConvertsDataTypes, AppendsLocationData, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* @return array * @return array
@ -113,9 +105,9 @@ class AccountUpdateRequest extends FormRequest
$rules = [ $rules = [
'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id), 'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id),
'type' => sprintf('in:%s', $types), 'type' => sprintf('in:%s', $types),
'iban' => 'iban|nullable', 'iban' => ['iban', 'nullable', new UniqueIban($account, $this->nullableString('type'))],
'bic' => 'bic|nullable', 'bic' => 'bic|nullable',
'account_number' => sprintf('between:1,255|nullable|uniqueAccountNumberForUser:%d', $account->id), 'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber($account, $this->nullableString('type'))],
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable', 'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
'opening_balance_date' => 'date|required_with:opening_balance|nullable', 'opening_balance_date' => 'date|required_with:opening_balance|nullable',
'virtual_balance' => 'numeric|nullable', 'virtual_balance' => 'numeric|nullable',
@ -134,6 +126,7 @@ class AccountUpdateRequest extends FormRequest
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly', 'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',
'notes' => 'min:0|max:65536', 'notes' => 'min:0|max:65536',
]; ];
return Location::requestRules($rules); return Location::requestRules($rules);
} }
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsValidAttachmentModel; use FireflyIII\Rules\IsValidAttachmentModel;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -34,18 +35,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class AttachmentStoreRequest extends FormRequest class AttachmentStoreRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -33,18 +34,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class AttachmentUpdateRequest extends FormRequest class AttachmentUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests\Autocomplete;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -33,18 +34,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class AutocompleteRequest extends FormRequest class AutocompleteRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* @return array * @return array
@ -60,7 +50,7 @@ class AutocompleteRequest extends FormRequest
$limit = 0 === $limit ? 10 : $limit; $limit = 0 === $limit ? 10 : $limit;
// remove 'initial balance' from allowed types. its internal // remove 'initial balance' from allowed types. its internal
$array = array_diff($array, [AccountType::INITIAL_BALANCE]); $array = array_diff($array, [AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION]);
return [ return [
'types' => $array, 'types' => $array,

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -33,18 +34,9 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class AvailableBudgetRequest extends FormRequest class AvailableBudgetRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -0,0 +1,73 @@
<?php
/**
* BudgetLimitStoreRequest.php
* Copyright (c) 2019 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;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class BudgetLimitStoreRequest
*
* @codeCoverageIgnore
*/
class BudgetLimitStoreRequest extends FormRequest
{
use ConvertsDataTypes, ChecksLogin;
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
return [
'budget_id' => $this->integer('budget_id'),
'start' => $this->date('start'),
'end' => $this->date('end'),
'amount' => $this->string('amount'),
'currency_id' => $this->integer('currency_id'),
'currency_code' => $this->string('currency_code'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
return [
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
'start' => 'required|before:end|date',
'end' => 'required|after:start|date',
'amount' => 'required|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
];
}
}

View File

@ -1,6 +1,6 @@
<?php <?php
/** /**
* BudgetLimitRequest.php * BudgetLimitUpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org * Copyright (c) 2019 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
@ -23,29 +23,18 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
/** /**
* Class BudgetLimitRequest * Class BudgetLimitUpdateRequest
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/ */
class BudgetLimitRequest extends FormRequest class BudgetLimitUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.
@ -85,21 +74,12 @@ class BudgetLimitRequest extends FormRequest
'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
]; ];
switch ($this->method()) {
default:
break;
case 'PUT':
case 'PATCH':
$rules['budget_id'] = 'required|exists:budgets,id|belongsToUser:budgets,id';
break;
}
// if request has a budget already, drop the rule. // if request has a budget already, drop the rule.
$budget = $this->route()->parameter('budget'); $budget = $this->route()->parameter('budget');
if (null !== $budget) { if (null !== $budget) {
unset($rules['budget_id']); unset($rules['budget_id']);
} }
return $rules; return $rules;
} }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest; use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -36,18 +37,7 @@ use Illuminate\Validation\Validator;
*/ */
class BudgetStoreRequest extends FormRequest class BudgetStoreRequest extends FormRequest
{ {
use ConvertsDataTypes, ValidatesAutoBudgetRequest; use ConvertsDataTypes, ValidatesAutoBudgetRequest, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest; use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -36,18 +37,7 @@ use Illuminate\Validation\Validator;
*/ */
class BudgetUpdateRequest extends FormRequest class BudgetUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes, ValidatesAutoBudgetRequest; use ConvertsDataTypes, ValidatesAutoBudgetRequest, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -35,18 +36,9 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class ConfigurationRequest extends FormRequest class ConfigurationRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -1,6 +1,6 @@
<?php <?php
/** /**
* CurrencyRequest.php * CurrencyStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org * Copyright (c) 2019 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
@ -24,30 +24,19 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
/** /**
* Class CurrencyRequest * Class CurrencyStoreRequest
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/ */
class CurrencyRequest extends FormRequest class CurrencyStoreRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.
@ -82,7 +71,7 @@ class CurrencyRequest extends FormRequest
*/ */
public function rules(): array public function rules(): array
{ {
$rules = [ return [
'name' => 'required|between:1,255|unique:transaction_currencies,name', 'name' => 'required|between:1,255|unique:transaction_currencies,name',
'code' => 'required|between:3,3|unique:transaction_currencies,code', 'code' => 'required|between:3,3|unique:transaction_currencies,code',
'symbol' => 'required|between:1,8|unique:transaction_currencies,symbol', 'symbol' => 'required|between:1,8|unique:transaction_currencies,symbol',
@ -91,20 +80,5 @@ class CurrencyRequest extends FormRequest
'default' => [new IsBoolean()], 'default' => [new IsBoolean()],
]; ];
switch ($this->method()) {
default:
break;
case 'PUT':
case 'PATCH':
$currency = $this->route()->parameter('currency_code');
$rules['name'] = 'required|between:1,255|unique:transaction_currencies,name,' . $currency->id;
$rules['code'] = 'required|between:3,3|unique:transaction_currencies,code,' . $currency->id;
$rules['symbol'] = 'required|between:1,8|unique:transaction_currencies,symbol,' . $currency->id;
break;
}
return $rules;
} }
} }

View File

@ -0,0 +1,84 @@
<?php
/**
* CurrencyUpdateRequest.php
* Copyright (c) 2019 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;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class CurrencyUpdateRequest
*
* @codeCoverageIgnore
*/
class CurrencyUpdateRequest extends FormRequest
{
use ConvertsDataTypes, ChecksLogin;
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$enabled = true;
$default = false;
if (null !== $this->get('enabled')) {
$enabled = $this->boolean('enabled');
}
if (null !== $this->get('default')) {
$default = $this->boolean('default');
}
return [
'name' => $this->string('name'),
'code' => $this->string('code'),
'symbol' => $this->string('symbol'),
'decimal_places' => $this->integer('decimal_places'),
'default' => $default,
'enabled' => $enabled,
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$currency = $this->route()->parameter('currency_code');
return [
'name' => sprintf('required|between:1,255|unique:transaction_currencies,name,%d', $currency->id),
'code' => sprintf('required|between:3,3|unique:transaction_currencies,code,%d', $currency->id),
'symbol' => sprintf('required|between:1,8|unique:transaction_currencies,symbol,%d', $currency->id),
'decimal_places' => 'between:0,20|numeric|min:0|max:20',
'enabled' => [new IsBoolean()],
'default' => [new IsBoolean()],
];
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -31,18 +32,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class DataDestroyRequest extends FormRequest class DataDestroyRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check() && !auth()->user()->hasRole('demo');
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -35,18 +36,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class DateRequest extends FormRequest class DateRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -1,6 +1,6 @@
<?php <?php
/** /**
* LinkTypeRequest.php * LinkTypeStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org * Copyright (c) 2019 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
@ -24,30 +24,19 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\LinkType; use FireflyIII\Models\LinkType;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
/** /**
* Class LinkTypeRequest * Class LinkTypeStoreRequest
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/ */
class LinkTypeRequest extends FormRequest class LinkTypeStoreRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.
@ -72,26 +61,10 @@ class LinkTypeRequest extends FormRequest
*/ */
public function rules(): array public function rules(): array
{ {
$rules = [ return [
'name' => 'required|unique:link_types,name|min:1', 'name' => 'required|unique:link_types,name|min:1',
'outward' => 'required|unique:link_types,outward|min:1|different:inward', 'outward' => 'required|unique:link_types,outward|min:1|different:inward',
'inward' => 'required|unique:link_types,inward|min:1|different:outward', 'inward' => 'required|unique:link_types,inward|min:1|different:outward',
]; ];
switch ($this->method()) {
default:
break;
case 'PUT':
case 'PATCH':
/** @var LinkType $linkType */
$linkType = $this->route()->parameter('linkType');
$rules['name'] = ['required', Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1'];
$rules['outward'] = ['required', 'different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1'];
$rules['inward'] = ['required', 'different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1'];
break;
}
return $rules;
} }
} }

View File

@ -0,0 +1,71 @@
<?php
/**
* LinkTypeUpdateRequest.php
* Copyright (c) 2019 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;
use FireflyIII\Models\LinkType;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
/**
* Class LinkTypeUpdateRequest
*
* @codeCoverageIgnore
*/
class LinkTypeUpdateRequest extends FormRequest
{
use ConvertsDataTypes, ChecksLogin;
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
return [
'name' => $this->string('name'),
'outward' => $this->string('outward'),
'inward' => $this->string('inward'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$linkType = $this->route()->parameter('linkType');
return [
'name' => ['required', Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1'],
'outward' => ['required', 'different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1'],
'inward' => ['required', 'different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1'],
];
}
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -34,18 +35,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class ObjectGroupUpdateRequest extends FormRequest class ObjectGroupUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* @return array * @return array

View File

@ -1,105 +0,0 @@
<?php
/**
* PiggyBankRequest.php
* Copyright (c) 2019 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;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Rules\IsAssetAccountId;
use FireflyIII\Rules\LessThanPiggyTarget;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class PiggyBankRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/
class PiggyBankRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
return [
'name' => $this->string('name'),
'account_id' => $this->integer('account_id'),
'targetamount' => $this->string('target_amount'),
'current_amount' => $this->string('current_amount'),
'startdate' => $this->date('start_date'),
'targetdate' => $this->date('target_date'),
'notes' => $this->nlString('notes'),
'order' => $this->integer('order'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$rules = [
'name' => 'required|between:1,255|uniquePiggyBankForUser',
'current_amount' => ['numeric', 'gte:0', 'lte:target_amount'],
'start_date' => 'date|nullable',
'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000',
];
switch ($this->method()) {
default:
break;
case 'PUT':
case 'PATCH':
/** @var PiggyBank $piggyBank */
$piggyBank = $this->route()->parameter('piggyBank');
$rules['name'] = 'between:1,255|uniquePiggyBankForUser:' . $piggyBank->id;
$rules['account_id'] = ['belongsToUser:accounts', new IsAssetAccountId];
$rules['target_amount'] = 'numeric|gt:0';
$rules['current_amount'] = ['numeric', 'gte:0', new LessThanPiggyTarget];
break;
}
return $rules;
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -33,18 +34,7 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class PiggyBankStoreRequest extends FormRequest class PiggyBankStoreRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -0,0 +1,89 @@
<?php
/**
* PiggyBankUpdateRequest.php
* Copyright (c) 2019 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;
use FireflyIII\Rules\IsAssetAccountId;
use FireflyIII\Rules\LessThanPiggyTarget;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class PiggyBankUpdateRequest
*
* @codeCoverageIgnore
*/
class PiggyBankUpdateRequest extends FormRequest
{
use ConvertsDataTypes, ChecksLogin;
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
// if the value isn't present, dont return it at all.
// TODO this should be the way to collect fields for all API things.
// TODO make sure piggy bank uses 'start_date' etc. until right up to DB update.
// TODO can we configure this and return it from config?
// TODO this is the way.
$fields = [
'name' => ['name', 'string'],
'account_id' => ['account_id', 'integer'],
'targetamount' => ['target_amount', 'string'],
'current_amount' => ['current_amount', 'string'],
'startdate' => ['start_date', 'date'],
'targetdate' => ['target_date', 'string'],
'notes' => ['notes', 'nlString'],
'order' => ['order', 'integer'],
'object_group' => ['object_group', 'string'],
'object_group_id' => ['object_group_id', 'integer'],
];
return $this->getAllData($fields);
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$piggyBank = $this->route()->parameter('piggyBank');
return [
'name' => 'between:1,255|uniquePiggyBankForUser:' . $piggyBank->id,
'current_amount' => ['numeric', 'gte:0', new LessThanPiggyTarget],
'target_amount' => 'numeric|gt:0',
'start_date' => 'date|nullable',
'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000',
'account_id' => ['belongsToUser:accounts', new IsAssetAccountId],
];
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -33,18 +34,9 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class PreferenceRequest extends FormRequest class PreferenceRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Rules\BelongsUser; use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRecurrenceData; use FireflyIII\Support\Request\GetRecurrenceData;
use FireflyIII\Validation\CurrencyValidation; use FireflyIII\Validation\CurrencyValidation;
@ -39,18 +40,9 @@ use Illuminate\Validation\Validator;
*/ */
class RecurrenceStoreRequest extends FormRequest class RecurrenceStoreRequest extends FormRequest
{ {
use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData; use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Recurrence; use FireflyIII\Models\Recurrence;
use FireflyIII\Rules\BelongsUser; use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRecurrenceData; use FireflyIII\Support\Request\GetRecurrenceData;
use FireflyIII\Validation\CurrencyValidation; use FireflyIII\Validation\CurrencyValidation;
@ -39,18 +40,9 @@ use Illuminate\Validation\Validator;
*/ */
class RecurrenceUpdateRequest extends FormRequest class RecurrenceUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData; use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -1,6 +1,6 @@
<?php <?php
/** /**
* RuleGroupRequest.php * RuleGroupStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org * Copyright (c) 2019 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
@ -25,29 +25,18 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\RuleGroup; use FireflyIII\Models\RuleGroup;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
* Class RuleGroupRequest * Class RuleGroupStoreRequest
* TODO AFTER 4.8,0: split this into two request classes.
*/ */
class RuleGroupRequest extends FormRequest class RuleGroupStoreRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.
@ -76,22 +65,10 @@ class RuleGroupRequest extends FormRequest
*/ */
public function rules(): array public function rules(): array
{ {
$rules = [ return [
'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title', 'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title',
'description' => 'between:1,5000|nullable', 'description' => 'between:1,5000|nullable',
'active' => [new IsBoolean], 'active' => [new IsBoolean],
]; ];
switch ($this->method()) {
default:
break;
case 'PUT':
case 'PATCH':
/** @var RuleGroup $ruleGroup */
$ruleGroup = $this->route()->parameter('ruleGroup');
$rules['title'] = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id;
break;
}
return $rules;
} }
} }

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -35,18 +36,9 @@ use Illuminate\Support\Collection;
*/ */
class RuleGroupTestRequest extends FormRequest class RuleGroupTestRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* @return array * @return array

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -34,18 +35,9 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class RuleGroupTriggerRequest extends FormRequest class RuleGroupTriggerRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* @return array * @return array

View File

@ -0,0 +1,74 @@
<?php
/**
* RuleGroupUpdateRequest.php
* Copyright (c) 2019 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;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* @codeCoverageIgnore
* Class RuleGroupUpdateRequest
*/
class RuleGroupUpdateRequest extends FormRequest
{
use ConvertsDataTypes, ChecksLogin;
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$active = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
return [
'title' => $this->string('title'),
'description' => $this->string('description'),
'active' => $active,
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$ruleGroup = $this->route()->parameter('ruleGroup');
return [
'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id,
'description' => 'between:1,5000|nullable',
'active' => [new IsBoolean],
];
}
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRuleConfiguration; use FireflyIII\Support\Request\GetRuleConfiguration;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -36,18 +37,9 @@ use function is_array;
*/ */
class RuleStoreRequest extends FormRequest class RuleStoreRequest extends FormRequest
{ {
use ConvertsDataTypes, GetRuleConfiguration; use ConvertsDataTypes, GetRuleConfiguration, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -34,18 +35,9 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class RuleTestRequest extends FormRequest class RuleTestRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* @return array * @return array

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -34,18 +35,9 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class RuleTriggerRequest extends FormRequest class RuleTriggerRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* @return array * @return array

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRuleConfiguration; use FireflyIII\Support\Request\GetRuleConfiguration;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -36,18 +37,9 @@ use function is_array;
*/ */
class RuleUpdateRequest extends FormRequest class RuleUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes, GetRuleConfiguration; use ConvertsDataTypes, GetRuleConfiguration, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Location; use FireflyIII\Models\Location;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -34,18 +36,8 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class TagStoreRequest extends FormRequest class TagStoreRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin, AppendsLocationData;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.
@ -54,20 +46,15 @@ class TagStoreRequest extends FormRequest
*/ */
public function getAll(): array public function getAll(): array
{ {
$hasLocation = false; $data = [
if ($this->has('longitude') && $this->has('latitude') && $this->has('zoom_level')) {
$hasLocation = true;
}
return [
'tag' => $this->string('tag'), 'tag' => $this->string('tag'),
'date' => $this->date('date'), 'date' => $this->date('date'),
'description' => $this->string('description'), 'description' => $this->string('description'),
'has_location' => $hasLocation, 'has_location' => true,
'longitude' => $this->string('longitude'),
'latitude' => $this->string('latitude'),
'zoom_level' => $this->integer('zoom_level'),
]; ];
$data = $this->appendLocationData($data, null);
return $data;
} }
/** /**

View File

@ -25,6 +25,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Location; use FireflyIII\Models\Location;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -35,18 +37,8 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class TagUpdateRequest extends FormRequest class TagUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin, AppendsLocationData;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.
@ -55,20 +47,15 @@ class TagUpdateRequest extends FormRequest
*/ */
public function getAll(): array public function getAll(): array
{ {
$updateLocation = false; $data = [
if ($this->has('longitude') && $this->has('latitude') && $this->has('zoom_level')) {
$updateLocation = true;
}
return [
'tag' => $this->string('tag'), 'tag' => $this->string('tag'),
'date' => $this->date('date'), 'date' => $this->date('date'),
'description' => $this->string('description'), 'description' => $this->string('description'),
'has_location' => $updateLocation, 'has_location' => true, // pretend location is present.
'longitude' => '' === $this->string('longitude') ? null : $this->string('longitude'),
'latitude' => '' === $this->string('latitude') ? null : $this->string('latitude'),
'zoom_level' => '' === $this->string('zoom_level') ? null : $this->integer('zoom_level'),
]; ];
$data = $this->appendLocationData($data, null);
return $data;
} }
/** /**

View File

@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -35,18 +36,9 @@ use Illuminate\Validation\Validator;
*/ */
class TransactionLinkRequest extends FormRequest class TransactionLinkRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data from the request. * Get all data from the request.

View File

@ -28,6 +28,7 @@ use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime; use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Support\NullArrayObject; use FireflyIII\Support\NullArrayObject;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\CurrencyValidation; use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\GroupValidation; use FireflyIII\Validation\GroupValidation;
@ -41,20 +42,7 @@ use Log;
*/ */
class TransactionStoreRequest extends FormRequest class TransactionStoreRequest extends FormRequest
{ {
use TransactionValidation, GroupValidation, CurrencyValidation, ConvertsDataTypes; use TransactionValidation, GroupValidation, CurrencyValidation, ConvertsDataTypes, ChecksLogin;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
Log::debug('Authorize TransactionStoreRequest');
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data. Is pretty complex because of all the ??-statements. * Get all data. Is pretty complex because of all the ??-statements.

View File

@ -28,6 +28,7 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Rules\BelongsUser; use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime; use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\GroupValidation; use FireflyIII\Validation\GroupValidation;
use FireflyIII\Validation\TransactionValidation; use FireflyIII\Validation\TransactionValidation;
@ -40,7 +41,7 @@ use Log;
*/ */
class TransactionUpdateRequest extends FormRequest class TransactionUpdateRequest extends FormRequest
{ {
use TransactionValidation, GroupValidation, ConvertsDataTypes; use TransactionValidation, GroupValidation, ConvertsDataTypes, ChecksLogin;
private array $arrayFields; private array $arrayFields;
private array $booleanFields; private array $booleanFields;
@ -50,16 +51,7 @@ class TransactionUpdateRequest extends FormRequest
private array $textareaFields; private array $textareaFields;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/** /**
* Get all data. Is pretty complex because of all the ??-statements. * Get all data. Is pretty complex because of all the ??-statements.
@ -382,26 +374,10 @@ class TransactionUpdateRequest extends FormRequest
// validate source/destination is equal, depending on the transaction journal type. // validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccountsForUpdate($validator, $transactionGroup); $this->validateEqualAccountsForUpdate($validator, $transactionGroup);
// If type is set, source + destination info is mandatory.
// Not going to do this. Not sure where the demand came from.
// validate that the currency fits the source and/or destination account. // validate that the currency fits the source and/or destination account.
// validate all account info // validate all account info
$this->validateAccountInformationUpdate($validator); $this->validateAccountInformationUpdate($validator);
// The currency info must match the accounts involved.
// Instead will ignore currency info as much as possible.
// TODO if the transaction_journal_id is empty, some fields are mandatory, like the amount!
// all journals must have a description
// // validate foreign currency info
//
//
// // make sure all splits have valid source + dest info
// the group must have a description if > 1 journal.
} }
); );
} }

View File

@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -34,10 +35,10 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class UserStoreRequest extends FormRequest class UserStoreRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/** /**
* Authorize logged in users. * Logged in + owner
* *
* @return bool * @return bool
*/ */

View File

@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@ -34,10 +35,10 @@ use Illuminate\Foundation\Http\FormRequest;
*/ */
class UserUpdateRequest extends FormRequest class UserUpdateRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes, ChecksLogin;
/** /**
* Authorize logged in users. * Logged in + owner
* *
* @return bool * @return bool
*/ */

View File

@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
/*
* CreateRequest.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/>.
*/
namespace FireflyIII\Api\V1\Requests\Webhook;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class CreateRequest
*/
class CreateRequest extends FormRequest
{
use ChecksLogin, ConvertsDataTypes;
/**
* @return array
*/
public function getData(): array
{
$triggers = array_flip(config('firefly.webhooks.triggers'));
$responses = array_flip(config('firefly.webhooks.responses'));
$deliveries = array_flip(config('firefly.webhooks.deliveries'));
$fields = [
'title' => ['title', 'string'],
'active' => ['active', 'boolean'],
'trigger' => ['trigger', 'string'],
'response' => ['response', 'string'],
'delivery' => ['delivery', 'string'],
'url' => ['url', 'string'],
];
// this is the way.
$return = $this->getAllData($fields);
$return['trigger'] = $triggers[$return['trigger']] ?? 0;
$return['response'] = $responses[$return['response']] ?? 0;
$return['delivery'] = $deliveries[$return['delivery']] ?? 0;
return $return;
}
/**
* Rules for this request.
*
* @return array
*/
public function rules(): array
{
$triggers = implode(',', array_values(config('firefly.webhooks.triggers')));
$responses = implode(',', array_values(config('firefly.webhooks.responses')));
$deliveries = implode(',', array_values(config('firefly.webhooks.deliveries')));
return [
'title' => 'required|between:1,512|uniqueObjectForUser:webhooks,title',
'active' => [new IsBoolean],
'trigger' => sprintf('required|in:%s', $triggers),
'response' => sprintf('required|in:%s', $responses),
'delivery' => sprintf('required|in:%s', $deliveries),
'url' => ['required', 'url', 'starts_with:https://', 'uniqueWebhook'],
];
}
}

View File

@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
/*
* UpdateRequest.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/>.
*/
namespace FireflyIII\Api\V1\Requests\Webhook;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class UpdateRequest
*/
class UpdateRequest extends FormRequest
{
use ChecksLogin, ConvertsDataTypes;
/**
* @return array
*/
public function getData(): array
{
$triggers = array_flip(config('firefly.webhooks.triggers'));
$responses = array_flip(config('firefly.webhooks.responses'));
$deliveries = array_flip(config('firefly.webhooks.deliveries'));
$fields = [
'title' => ['title', 'string'],
'active' => ['active', 'boolean'],
'trigger' => ['trigger', 'string'],
'response' => ['response', 'string'],
'delivery' => ['delivery', 'string'],
'url' => ['url', 'string'],
];
// this is the way.
$return = $this->getAllData($fields);
$return['trigger'] = $triggers[$return['trigger']] ?? 0;
$return['response'] = $responses[$return['response']] ?? 0;
$return['delivery'] = $deliveries[$return['delivery']] ?? 0;
$return['secret'] = null !== $this->get('secret');
return $return;
}
/**
* Rules for this request.
*
* @return array
*/
public function rules(): array
{
$triggers = implode(',', array_values(config('firefly.webhooks.triggers')));
$responses = implode(',', array_values(config('firefly.webhooks.responses')));
$deliveries = implode(',', array_values(config('firefly.webhooks.deliveries')));
$webhook = $this->route()->parameter('webhook');
return [
'title' => sprintf('between:1,512|uniqueObjectForUser:webhooks,title,%d', $webhook->id),
'active' => [new IsBoolean],
'trigger' => sprintf('required|in:%s', $triggers),
'response' => sprintf('required|in:%s', $responses),
'delivery' => sprintf('required|in:%s', $deliveries),
'url' => ['required', 'url', 'starts_with:https://', sprintf('uniqueExistingWebhook:%d', $webhook->id)],
];
}
}

View File

@ -0,0 +1,175 @@
<?php
declare(strict_types=1);
/*
* AppendBudgetLimitPeriods.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/>.
*/
namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Console\Command;
use Log;
class AppendBudgetLimitPeriods extends Command
{
public const CONFIG_NAME = '550_budget_limit_periods';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Append budget limits with their (estimated) timeframe.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:budget-limit-periods {--F|force : Force the execution of this command.}';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
$start = microtime(true);
if ($this->isExecuted() && true !== $this->option('force')) {
$this->warn('This command has already been executed.');
return 0;
}
$this->theresNoLimit();
$this->markAsExecuted();
$end = round(microtime(true) - $start, 2);
$this->info(sprintf('Fixed budget limits in %s seconds.', $end));
return 0;
}
/**
* @return bool
*/
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
}
return false; // @codeCoverageIgnore
}
/**
* @param BudgetLimit $limit
*
* @return string|null
*/
private function getLimitPeriod(BudgetLimit $limit): ?string
{
// is daily
if ($limit->end_date->isSameDay($limit->start_date)) {
return 'daily';
}
// is weekly
if ('1' === $limit->start_date->format('N') && '7' === $limit->end_date->format('N') && 6 === $limit->end_date->diffInDays($limit->start_date)) {
return 'weekly';
}
// is monthly
if (
'1' === $limit->start_date->format('j') // first day
&& $limit->end_date->format('j') === $limit->end_date->format('t') // last day
&& $limit->start_date->isSameMonth($limit->end_date)
) {
return 'monthly';
}
// is quarter
$start = ['1-1', '1-4', '1-7', '1-10'];
$end = ['31-3', '30-6', '30-9', '31-12'];
if (
in_array($limit->start_date->format('j-n'), $start, true) // start of quarter
&& in_array($limit->end_date->format('j-n'), $end, true) // end of quarter
&& 2 === $limit->start_date->diffInMonths($limit->end_date)
) {
return 'quarterly';
}
// is half year
$start = ['1-1', '1-7'];
$end = ['30-6', '31-12'];
if (
in_array($limit->start_date->format('j-n'), $start) // start of quarter
&& in_array($limit->end_date->format('j-n'), $end) // end of quarter
&& 5 === $limit->start_date->diffInMonths($limit->end_date)
) {
return 'half_year';
}
// is yearly
if ('1-1' === $limit->start_date->format('j-n') && '31-12' === $limit->end_date->format('j-n')) {
return 'yearly';
}
return null;
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
/**
*
*/
private function theresNoLimit(): void
{
$limits = BudgetLimit::whereNull('period')->get();
/** @var BudgetLimit $limit */
foreach ($limits as $limit) {
$this->fixLimit($limit);
}
}
/**
* @param BudgetLimit $limit
*/
private function fixLimit(BudgetLimit $limit)
{
$period = $this->getLimitPeriod($limit);
if (null === $period) {
$message = sprintf('Could not guesstimate budget limit #%d (%s - %s) period.', $limit->id, $limit->start_date->format('Y-m-d'), $limit->end_date->format('Y-m-d'));
$this->warn($message);
Log::warning($message);
return;
}
$limit->period = $period;
$limit->save();
$msg = sprintf('Budget limit #%d (%s - %s) period is "%s".', $limit->id, $limit->start_date->format('Y-m-d'), $limit->end_date->format('Y-m-d'), $period);
Log::debug($msg);
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* DestroyedTransactionGroup.php
* Copyright (c) 2019 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\Events;
use FireflyIII\Models\TransactionGroup;
use Illuminate\Queue\SerializesModels;
/**
* Class DestroyedTransactionGroup.
*
* @codeCoverageIgnore
*/
class DestroyedTransactionGroup extends Event
{
use SerializesModels;
public TransactionGroup $transactionGroup;
/**
* Create a new event instance.
*
* @param TransactionGroup $transactionGroup
*/
public function __construct(TransactionGroup $transactionGroup)
{
$this->transactionGroup = $transactionGroup;
}
}

View File

@ -0,0 +1,48 @@
<?php
/*
* DestroyedTransactionLink.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\Events;
use FireflyIII\Models\TransactionJournalLink;
use Illuminate\Queue\SerializesModels;
/**
* Class DestroyedTransactionLink
*/
class DestroyedTransactionLink extends Event
{
use SerializesModels;
private TransactionJournalLink $link;
/**
* DestroyedTransactionLink constructor.
*
* @param TransactionJournalLink $link
*/
public function __construct(TransactionJournalLink $link)
{
$this->link = $link;
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
/*
* RequestedSendWebhookMessages.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/>.
*/
namespace FireflyIII\Events;
use Illuminate\Queue\SerializesModels;
class RequestedSendWebhookMessages extends Event
{
use SerializesModels;
}

View File

@ -36,10 +36,8 @@ class StoredTransactionGroup extends Event
{ {
use SerializesModels; use SerializesModels;
/** @var bool */ public bool $applyRules;
public $applyRules; public TransactionGroup $transactionGroup;
/** @var TransactionGroup The group that was stored. */
public $transactionGroup;
/** /**

View File

@ -0,0 +1,47 @@
<?php
/*
* StoredTransactionLink.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\Events;
use FireflyIII\Models\TransactionJournalLink;
use Illuminate\Queue\SerializesModels;
/**
* Class StoredTransactionLink
*/
class StoredTransactionLink extends Event
{
use SerializesModels;
private TransactionJournalLink $link;
/**
* DestroyedTransactionLink constructor.
*
* @param TransactionJournalLink $link
*/
public function __construct(TransactionJournalLink $link)
{
$this->link = $link;
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* UpdatedTransactionLink.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\Events;
use FireflyIII\Models\TransactionJournalLink;
use Illuminate\Queue\SerializesModels;
/**
* Class UpdatedTransactionLink
*/
class UpdatedTransactionLink extends Event
{
use SerializesModels;
private TransactionJournalLink $link;
/**
* DestroyedTransactionLink constructor.
*
* @param TransactionJournalLink $link
*/
public function __construct(TransactionJournalLink $link)
{
$this->link = $link;
}
}

View File

@ -116,6 +116,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
return redirect(route('tags.index')); return redirect(route('tags.index'));
break; break;
case 'categories.show': case 'categories.show':
case 'categories.show.all':
$request->session()->reflash(); $request->session()->reflash();
return redirect(route('categories.index')); return redirect(route('categories.index'));

View File

@ -41,10 +41,8 @@ class RecurrenceFactory
{ {
use TransactionTypeTrait, RecurringTransactionTrait; use TransactionTypeTrait, RecurringTransactionTrait;
/** @var MessageBag */ private MessageBag $errors;
private $errors; private User $user;
/** @var User */
private $user;
/** /**
@ -54,9 +52,6 @@ class RecurrenceFactory
*/ */
public function __construct() public function __construct()
{ {
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
$this->errors = new MessageBag; $this->errors = new MessageBag;
} }

View File

@ -38,18 +38,12 @@ use Log;
*/ */
class TransactionFactory class TransactionFactory
{ {
/** @var Account */ private Account $account;
private $account; private TransactionCurrency $currency;
/** @var TransactionCurrency */ private ?TransactionCurrency $foreignCurrency;
private $currency; private TransactionJournal $journal;
/** @var TransactionCurrency */ private bool $reconciled;
private $foreignCurrency; private User $user;
/** @var TransactionJournal */
private $journal;
/** @var bool */
private $reconciled;
/** @var User */
private $user;
/** /**
@ -59,9 +53,6 @@ class TransactionFactory
*/ */
public function __construct() public function __construct()
{ {
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
$this->reconciled = false; $this->reconciled = false;
} }

View File

@ -75,30 +75,7 @@ class TransactionJournalFactory
public function __construct() public function __construct()
{ {
$this->errorOnHash = false; $this->errorOnHash = false;
// TODO move valid meta fields to config. $this->fields = config('firefly.journal_meta_fields');
$this->fields = [
// sepa
'sepa_cc', 'sepa_ct_op', 'sepa_ct_id',
'sepa_db', 'sepa_country', 'sepa_ep',
'sepa_ci', 'sepa_batch_id', 'external_uri',
// dates
'interest_date', 'book_date', 'process_date',
'due_date', 'payment_date', 'invoice_date',
// others
'recurrence_id', 'internal_reference', 'bunq_payment_id',
'import_hash', 'import_hash_v2', 'external_id', 'original_source',
// recurring transactions
'recurrence_total', 'recurrence_count',
];
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
$this->currencyRepository = app(CurrencyRepositoryInterface::class); $this->currencyRepository = app(CurrencyRepositoryInterface::class);
$this->typeRepository = app(TransactionTypeRepositoryInterface::class); $this->typeRepository = app(TransactionTypeRepositoryInterface::class);
$this->billRepository = app(BillRepositoryInterface::class); $this->billRepository = app(BillRepositoryInterface::class);
@ -267,7 +244,8 @@ class TransactionJournalFactory
return null; return null;
} }
// TODO typeOverrule: the account validator may have another opinion on the transaction type. // typeOverrule: the account validator may have another opinion on the transaction type.
// not sure what to do with this.
/** create or get source and destination accounts */ /** create or get source and destination accounts */
$sourceInfo = [ $sourceInfo = [
@ -356,7 +334,6 @@ class TransactionJournalFactory
// verify that journal has two transactions. Otherwise, delete and cancel. // verify that journal has two transactions. Otherwise, delete and cancel.
// TODO this can't be faked so it can't be tested.
$journal->completed = true; $journal->completed = true;
$journal->save(); $journal->save();

View File

@ -34,18 +34,6 @@ use Log;
*/ */
class TransactionJournalMetaFactory class TransactionJournalMetaFactory
{ {
/**
* Constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/** /**
* @param array $data * @param array $data
* *

View File

@ -33,18 +33,6 @@ use Log;
*/ */
class TransactionTypeFactory class TransactionTypeFactory
{ {
/**
* Constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/** /**
* @param string $type * @param string $type
* *

View File

@ -30,18 +30,6 @@ use Log;
*/ */
class ChartJsGenerator implements GeneratorInterface class ChartJsGenerator implements GeneratorInterface
{ {
/**
* Constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/** /**
* Expects data as:. * Expects data as:.
* *

View File

@ -52,7 +52,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
*/ */
public function __construct() public function __construct()
{ {
$this->expenses = new Collection; $this->expenses = [];
} }
/** /**

View File

@ -1,7 +1,8 @@
<?php <?php
/** declare(strict_types=1);
* ExchangeRateInterface.php /*
* Copyright (c) 2019 james@firefly-iii.org * MessageGeneratorInterface.php
* Copyright (c) 2020 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@ -18,33 +19,40 @@
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
declare(strict_types=1);
namespace FireflyIII\Services\Currency; namespace FireflyIII\Generator\Webhook;
use Carbon\Carbon;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Support\Collection;
/** /**
* Interface ExchangeRateInterface * Interface MessageGeneratorInterface
*/ */
interface ExchangeRateInterface interface MessageGeneratorInterface
{ {
/** /**
* @param TransactionCurrency $fromCurrency * @return int
* @param TransactionCurrency $toCurrency
* @param Carbon $date
*
* @return CurrencyExchangeRate
*/ */
public function getRate(TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date): CurrencyExchangeRate; public function getVersion(): int;
/**
*
*/
public function generateMessages(): void;
/** /**
* @param User $user * @param User $user
*
* @return mixed
*/ */
public function setUser(User $user); public function setUser(User $user): void;
/**
* @param Collection $objects
*/
public function setObjects(Collection $objects): void;
/**
* @param int $trigger
*/
public function setTrigger(int $trigger): void;
} }

View File

@ -0,0 +1,237 @@
<?php
declare(strict_types=1);
/*
* WebhookMessageGenerator.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/>.
*/
namespace FireflyIII\Generator\Webhook;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\Webhook;
use FireflyIII\Models\WebhookMessage;
use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Log;
use Ramsey\Uuid\Uuid;
use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class StandardMessageGenerator
*/
class StandardMessageGenerator implements MessageGeneratorInterface
{
private int $version = 0;
private User $user;
private Collection $objects;
private int $trigger;
private Collection $webhooks;
/**
*
*/
public function generateMessages(): void
{
Log::debug(__METHOD__);
// get the webhooks:
$this->webhooks = $this->getWebhooks();
// do some debugging
Log::debug(
sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count())
);
$this->run();
}
/**
* @param User $user
*/
public function setUser(User $user): void
{
$this->user = $user;
}
/**
* @param Collection $objects
*/
public function setObjects(Collection $objects): void
{
$this->objects = $objects;
}
/**
* @param int $trigger
*/
public function setTrigger(int $trigger): void
{
$this->trigger = $trigger;
}
/**
* @return Collection
*/
private function getWebhooks(): Collection
{
return $this->user->webhooks()->where('active', 1)->where('trigger', $this->trigger)->get(['webhooks.*']);
}
/**
*
*/
private function run(): void
{
Log::debug('Now in StandardMessageGenerator::run');
/** @var Webhook $webhook */
foreach ($this->webhooks as $webhook) {
$this->runWebhook($webhook);
}
Log::debug('Done with StandardMessageGenerator::run');
}
/**
* @param Webhook $webhook
*/
private function runWebhook(Webhook $webhook): void
{
Log::debug(sprintf('Now in runWebhook(#%d)', $webhook->id));
/** @var Model $object */
foreach ($this->objects as $object) {
$this->generateMessage($webhook, $object);
}
}
/**
* @param Webhook $webhook
* @param Model $model
*/
private function generateMessage(Webhook $webhook, Model $model): void
{
$class = get_class($model);
Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id));
$uuid = Uuid::uuid4();
$basicMessage = [
'uuid' => $uuid->toString(),
'user_id' => 0,
'trigger' => config('firefly.webhooks.triggers')[$webhook->trigger],
'response' => config('firefly.webhooks.responses')[$webhook->response],
'url' => $webhook->url,
'version' => sprintf('v%d', $this->getVersion()),
'content' => [],
];
// depends on the model how user_id is set:
switch ($class) {
default:
Log::error(sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id));
return;
case TransactionGroup::class:
/** @var TransactionGroup $model */
$basicMessage['user_id'] = $model->user->id;
break;
}
// then depends on the response what to put in the message:
switch ($webhook->response) {
default:
Log::error(
sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response)
);
return;
case Webhook::RESPONSE_NONE:
$basicMessage['content'] = [];
break;
case Webhook::RESPONSE_TRANSACTIONS:
$transformer = new TransactionGroupTransformer;
try {
$basicMessage['content'] = $transformer->transformObject($model);
} catch (FireflyException $e) {
Log::error(
sprintf('The transformer could not include the requested transaction group for webhook #%d: %s', $webhook->id, $e->getMessage())
);
return;
}
break;
case Webhook::RESPONSE_ACCOUNTS:
$accounts = $this->collectAccounts($model);
foreach ($accounts as $account) {
$transformer = new AccountTransformer;
$transformer->setParameters(new ParameterBag);
$basicMessage['content'][] = $transformer->transform($account);
}
}
$this->storeMessage($webhook, $basicMessage);
}
/**
* @param TransactionGroup $transactionGroup
*
* @return Collection
*/
private function collectAccounts(TransactionGroup $transactionGroup): Collection
{
$accounts = new Collection;
/** @var TransactionJournal $journal */
foreach ($transactionGroup->transactionJournals as $journal) {
/** @var Transaction $transaction */
foreach ($journal->transactions as $transaction) {
$accounts->push($transaction->account);
}
}
return $accounts->unique();
}
/**
* @param Webhook $webhook
* @param array $message
*
* @return WebhookMessage
*/
private function storeMessage(Webhook $webhook, array $message): WebhookMessage
{
$webhookMessage = new WebhookMessage;
$webhookMessage->webhook()->associate($webhook);
$webhookMessage->sent = false;
$webhookMessage->errored = false;
$webhookMessage->uuid = $message['uuid'];
$webhookMessage->message = $message;
$webhookMessage->save();
Log::debug(sprintf('Stored new webhook message #%d', $webhookMessage->id));
return $webhookMessage;
}
/**
* @inheritDoc
*/
public function getVersion(): int
{
return $this->version;
}
}

View File

@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
/*
* DestroyedGroupEventHandler.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/>.
*/
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\DestroyedTransactionGroup;
use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
use FireflyIII\Models\Webhook;
use Illuminate\Support\Collection;
use Log;
/**
* Class DestroyedGroupEventHandler
*/
class DestroyedGroupEventHandler
{
/**
* @param DestroyedTransactionGroup $destroyedGroupEvent
*/
public function triggerWebhooks(DestroyedTransactionGroup $destroyedGroupEvent): void
{
Log::debug('DestroyedTransactionGroup:triggerWebhooks');
$group = $destroyedGroupEvent->transactionGroup;
$user = $group->user;
/** @var MessageGeneratorInterface $engine */
$engine = app(MessageGeneratorInterface::class);
$engine->setUser($user);
$engine->setObjects(new Collection([$group]));
$engine->setTrigger(Webhook::TRIGGER_DESTROY_TRANSACTION);
$engine->generateMessages();
event(new RequestedSendWebhookMessages);
}
}

View File

@ -22,11 +22,15 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events; namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Events\StoredTransactionGroup; use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\Webhook;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface; use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\TransactionRules\Engine\RuleEngine; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\TransactionRules\Engine\RuleEngineInterface; use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
use Illuminate\Support\Collection;
use Log; use Log;
/** /**
@ -59,15 +63,45 @@ class StoredGroupEventHandler
// collect rules: // collect rules:
$ruleRepository = app(RuleRepositoryInterface::class); $ruleRepository = app(RuleRepositoryInterface::class);
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$ruleRepository->setUser($storedGroupEvent->transactionGroup->user); $ruleRepository->setUser($storedGroupEvent->transactionGroup->user);
$rules = $ruleRepository->getStoreRules(); $ruleGroupRepository->setUser($storedGroupEvent->transactionGroup->user);
// file rule engine. // add the groups to the rule engine.
// it should run the rules in the group and cancel the group if necessary.
$groups = $ruleGroupRepository->getRuleGroupsWithRules();
// create and fire rule engine.
$newRuleEngine = app(RuleEngineInterface::class); $newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($storedGroupEvent->transactionGroup->user); $newRuleEngine->setUser($storedGroupEvent->transactionGroup->user);
$newRuleEngine->addOperator(['type' => 'journal_id', 'value' => $journalIds]); $newRuleEngine->addOperator(['type' => 'journal_id', 'value' => $journalIds]);
$newRuleEngine->setRules($rules); $newRuleEngine->setRuleGroups($groups);
$newRuleEngine->fire(); $newRuleEngine->fire();
} }
/**
* This method processes all webhooks that respond to the "stored transaction group" trigger (100)
*
* @param StoredTransactionGroup $storedGroupEvent
*/
public function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void
{
Log::debug(__METHOD__);
$group = $storedGroupEvent->transactionGroup;
$user = $group->user;
/** @var MessageGeneratorInterface $engine */
$engine = app(MessageGeneratorInterface::class);
$engine->setUser($user);
// tell the generator which trigger it should look for
$engine->setTrigger(Webhook::TRIGGER_STORE_TRANSACTION);
// tell the generator which objects to process
$engine->setObjects(new Collection([$group]));
// tell the generator to generate the messages
$engine->generateMessages();
// trigger event to send them:
event(new RequestedSendWebhookMessages);
}
} }

View File

@ -22,14 +22,17 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events; namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Events\UpdatedTransactionGroup; use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Models\Webhook;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface; use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\TransactionRules\Engine\RuleEngine;
use FireflyIII\TransactionRules\Engine\RuleEngineInterface; use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
use Illuminate\Support\Collection;
use Log; use Log;
/** /**
@ -112,4 +115,21 @@ class UpdatedGroupEventHandler
$newRuleEngine->fire(); $newRuleEngine->fire();
} }
/**
* @param UpdatedTransactionGroup $updatedGroupEvent
*/
public function triggerWebhooks(UpdatedTransactionGroup $updatedGroupEvent): void
{
Log::debug('UpdatedGroupEventHandler:triggerWebhooks');
$group = $updatedGroupEvent->transactionGroup;
$user = $group->user;
/** @var MessageGeneratorInterface $engine */
$engine = app(MessageGeneratorInterface::class);
$engine->setUser($user);
$engine->setObjects(new Collection([$group]));
$engine->setTrigger(Webhook::TRIGGER_UPDATE_TRANSACTION);
$engine->generateMessages();
event(new RequestedSendWebhookMessages);
}
} }

View File

@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
/*
* WebhookEventHandler.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/>.
*/
namespace FireflyIII\Handlers\Events;
use FireflyIII\Jobs\SendWebhookMessage;
use FireflyIII\Models\WebhookMessage;
use Log;
/**
* Class WebhookEventHandler
*/
class WebhookEventHandler
{
/**
* Will try to send at most 3 messages so the flow doesn't get broken too much.
*/
public function sendWebhookMessages(): void
{
// kick off the job!
$messages = WebhookMessage
::where('webhook_messages.sent', 0)
->where('webhook_messages.errored', 0)
->get(['webhook_messages.*'])
->filter(
function (WebhookMessage $message) {
return $message->webhookAttempts()->count() <= 2;
}
)->splice(0, 3);
Log::debug(sprintf('Found %d webhook message(s) ready to be send.', $messages->count()));
foreach ($messages as $message) {
SendWebhookMessage::dispatch($message)->afterResponse();
}
}
}

View File

@ -70,10 +70,6 @@ class AttachmentHelper implements AttachmentHelperInterface
$this->messages = new MessageBag; $this->messages = new MessageBag;
$this->attachments = new Collection; $this->attachments = new Collection;
$this->uploadDisk = Storage::disk('upload'); $this->uploadDisk = Storage::disk('upload');
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
} }

View File

@ -165,6 +165,16 @@ class GroupCollector implements GroupCollectorInterface
*/ */
public function getGroups(): Collection public function getGroups(): Collection
{ {
$filterQuery = false;
// now filter the query according to the page and the limit (if necessary)
if ($filterQuery) {
if (null !== $this->limit && null !== $this->page) {
$offset = ($this->page - 1) * $this->limit;
$this->query->take($this->limit)->skip($offset);
}
}
/** @var Collection $result */ /** @var Collection $result */
$result = $this->query->get($this->fields); $result = $this->query->get($this->fields);
@ -173,11 +183,13 @@ class GroupCollector implements GroupCollectorInterface
$this->total = $collection->count(); $this->total = $collection->count();
// now filter the array according to the page and the limit (if necessary) // now filter the array according to the page and the limit (if necessary)
if (!$filterQuery) {
if (null !== $this->limit && null !== $this->page) { if (null !== $this->limit && null !== $this->page) {
$offset = ($this->page - 1) * $this->limit; $offset = ($this->page - 1) * $this->limit;
return $collection->slice($offset, $this->limit); return $collection->slice($offset, $this->limit);
} }
}
return $collection; return $collection;
} }
@ -193,27 +205,10 @@ class GroupCollector implements GroupCollectorInterface
if (0 === $this->limit) { if (0 === $this->limit) {
$this->setLimit(50); $this->setLimit(50);
} }
return new LengthAwarePaginator($set, $this->total, $this->limit, $this->page); return new LengthAwarePaginator($set, $this->total, $this->limit, $this->page);
} }
/**
* Return the sum of all journals.
* TODO ignores the currency.
*
* @return string
*/
public function getSum(): string
{
$journals = $this->getExtractedJournals();
$sum = '0';
/** @var array $journal */
foreach ($journals as $journal) {
$amount = (string) $journal['amount'];
$sum = bcadd($sum, $amount);
}
return $sum;
}
/** /**
* Limit results to a specific currency, either foreign or normal one. * Limit results to a specific currency, either foreign or normal one.
@ -260,6 +255,20 @@ class GroupCollector implements GroupCollectorInterface
return $this; return $this;
} }
/**
* Limit the result to a set of specific transaction groups.
*
* @param array $groupIds
*
* @return GroupCollectorInterface
*/
public function setIds(array $groupIds): GroupCollectorInterface {
$this->query->whereIn('transaction_groups.id', $groupIds);
return $this;
}
/** /**
* Limit the number of returned entries. * Limit the number of returned entries.
* *
@ -440,6 +449,7 @@ class GroupCollector implements GroupCollectorInterface
$this->startQuery(); $this->startQuery();
} }
return $this; return $this;
} }

View File

@ -105,13 +105,6 @@ interface GroupCollectorInterface
*/ */
public function getPaginatedGroups(): LengthAwarePaginator; public function getPaginatedGroups(): LengthAwarePaginator;
/**
* Return the sum of all journals.
*
* @return string
*/
public function getSum(): string;
/** /**
* Define which accounts can be part of the source and destination transactions. * Define which accounts can be part of the source and destination transactions.
* *
@ -247,6 +240,15 @@ interface GroupCollectorInterface
*/ */
public function setJournalIds(array $journalIds): GroupCollectorInterface; public function setJournalIds(array $journalIds): GroupCollectorInterface;
/**
* Limit the result to a set of specific transaction groups.
*
* @param array $groupIds
*
* @return GroupCollectorInterface
*/
public function setIds(array $groupIds): GroupCollectorInterface;
/** /**
* Limit the number of returned entries. * Limit the number of returned entries.
* *

View File

@ -39,10 +39,6 @@ class FiscalHelper implements FiscalHelperInterface
public function __construct() public function __construct()
{ {
$this->useCustomFiscalYear = app('preferences')->get('customFiscalYear', false)->data; $this->useCustomFiscalYear = app('preferences')->get('customFiscalYear', false)->data;
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
} }
/** /**

View File

@ -44,9 +44,6 @@ class Help implements HelpInterface
*/ */
public function __construct() public function __construct()
{ {
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
$this->userAgent = sprintf($this->userAgent, config('firefly.version')); $this->userAgent = sprintf($this->userAgent, config('firefly.version'));
} }

View File

@ -47,16 +47,6 @@ class NetWorth implements NetWorthInterface
/** @var User */ /** @var User */
private $user; private $user;
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/** /**
* Returns the user's net worth in an array with the following layout: * Returns the user's net worth in an array with the following layout:
* *

View File

@ -27,6 +27,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -39,16 +40,6 @@ use Log;
*/ */
class PopupReport implements PopupReportInterface class PopupReport implements PopupReportInterface
{ {
/**
* Constructor.
*/
public function __construct()
{
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/** /**
* Collect the transactions for one account and one budget. * Collect the transactions for one account and one budget.
* *
@ -216,10 +207,17 @@ class PopupReport implements PopupReportInterface
$repository = app(JournalRepositoryInterface::class); $repository = app(JournalRepositoryInterface::class);
$repository->setUser($account->user); $repository->setUser($account->user);
$accountRepository = app(AccountRepositoryInterface::class);
$accountRepository->setUser($account->user);
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account])) // set report accounts + the request accounts:
$set = $attributes['accounts'] ?? new Collection;
$set->push($account);
$collector->setBothAccounts($set)
->setRange($attributes['startDate'], $attributes['endDate']) ->setRange($attributes['startDate'], $attributes['endDate'])
->withAccountInformation() ->withAccountInformation()
->withBudgetInformation() ->withBudgetInformation()

View File

@ -49,12 +49,6 @@ class ReportHelper implements ReportHelperInterface
public function __construct(BudgetRepositoryInterface $budgetRepository) public function __construct(BudgetRepositoryInterface $budgetRepository)
{ {
$this->budgetRepository = $budgetRepository; $this->budgetRepository = $budgetRepository;
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
} }
/** /**

View File

@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
/*
* Sha3SignatureGenerator.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/>.
*/
namespace FireflyIII\Helpers\Webhook;
use FireflyIII\Models\WebhookMessage;
use JsonException;
/**
* Class Sha3SignatureGenerator
*/
class Sha3SignatureGenerator implements SignatureGeneratorInterface
{
private int $version = 1;
/**
* @inheritDoc
*/
public function getVersion(): int
{
return $this->version;
}
/**
* @inheritDoc
*/
public function generate(WebhookMessage $message): string
{
try {
$json = json_encode($message->message, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
// TODO needs FireflyException.
return sprintf('t=1,v%d=err-invalid-signature', $this->getVersion());
}
// signature v1 is generated using the following structure:
// The signed_payload string is created by concatenating:
// The timestamp (as a string)
// The character .
// The character .
// The actual JSON payload (i.e., the request body)
$timestamp = time();
$payload = sprintf('%s.%s', $timestamp, $json);
$signature = hash_hmac('sha3-256', $payload, $message->webhook->secret, false);
// signature string:
// header included in each signed event contains a timestamp and one or more signatures.
// The timestamp is prefixed by t=, and each signature is prefixed by a scheme.
// Schemes start with v, followed by an integer. Currently, the only valid live signature scheme is v1.
return sprintf('t=%s,v%d=%s', $timestamp, $this->getVersion(), $signature);
}
}

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
/*
* SignatureGeneratorInterface.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/>.
*/
namespace FireflyIII\Helpers\Webhook;
use FireflyIII\Models\WebhookMessage;
/**
* Interface SignatureGeneratorInterface
*/
interface SignatureGeneratorInterface
{
/**
* Return the version of this signature generator.
*
* @return int
*/
public function getVersion(): int;
/**
* @param WebhookMessage $message
*
* @return string
*/
public function generate(WebhookMessage $message): string;
}

View File

@ -125,6 +125,7 @@ class ShowController extends Controller
->setPage($page)->withAccountInformation()->withCategoryInformation() ->setPage($page)->withAccountInformation()->withCategoryInformation()
->setRange($start, $end); ->setRange($start, $end);
$groups = $collector->getPaginatedGroups(); $groups = $collector->getPaginatedGroups();
$groups->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')])); $groups->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]));
$showAll = false; $showAll = false;
$balance = app('steam')->balance($account, $end); $balance = app('steam')->balance($account, $end);

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Auth; namespace FireflyIII\Http\Controllers\Auth;
use Adldap; use Adldap;
use Cookie;
use DB; use DB;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Providers\RouteServiceProvider; use FireflyIII\Providers\RouteServiceProvider;
@ -202,6 +203,10 @@ class LoginController extends Controller
session()->flash('error', trans('firefly.cant_logout_guard')); session()->flash('error', trans('firefly.cant_logout_guard'));
} }
// also logout current 2FA tokens.
$cookieName = config('google2fa.cookie_name', 'google2fa_token');
Cookie::forget($cookieName);
$this->guard()->logout(); $this->guard()->logout();
$request->session()->invalidate(); $request->session()->invalidate();

View File

@ -75,7 +75,7 @@ class CreateController extends Controller
/** @var array $billPeriods */ /** @var array $billPeriods */
$billPeriods = config('firefly.bill_periods'); $billPeriods = config('firefly.bill_periods');
foreach ($billPeriods as $current) { foreach ($billPeriods as $current) {
$periods[$current] = strtolower((string) trans('firefly.repeat_freq_' . $current)); $periods[$current] = (string) trans('firefly.repeat_freq_' . $current);
} }
$subTitle = (string) trans('firefly.create_new_bill'); $subTitle = (string) trans('firefly.create_new_bill');
$defaultCurrency = app('amount')->getDefaultCurrency(); $defaultCurrency = app('amount')->getDefaultCurrency();

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