mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-03-07 00:11:45 +00:00
Compare commits
15 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2d1e8e184 | ||
|
|
19d8f46f24 | ||
|
|
9ac991edd7 | ||
|
|
e85f06792b | ||
|
|
b66f95f1dc | ||
|
|
4d63146524 | ||
|
|
695f990236 | ||
|
|
e882530a69 | ||
|
|
993a2491e9 | ||
|
|
f6ea517b5d | ||
|
|
6f4143bb79 | ||
|
|
4a2c77c6b7 | ||
|
|
0e62f980b0 | ||
|
|
41533fd922 | ||
|
|
d6b5fbe341 |
12
.ci/php-cs-fixer/composer.lock
generated
12
.ci/php-cs-fixer/composer.lock
generated
@@ -1264,16 +1264,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v8.0.6",
|
||||
"version": "v8.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "488285876e807a4777f074041d8bb508623419fa"
|
||||
"reference": "15ed9008a4ebe2d6a78e4937f74e0c13ef2e618a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/488285876e807a4777f074041d8bb508623419fa",
|
||||
"reference": "488285876e807a4777f074041d8bb508623419fa",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/15ed9008a4ebe2d6a78e4937f74e0c13ef2e618a",
|
||||
"reference": "15ed9008a4ebe2d6a78e4937f74e0c13ef2e618a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1330,7 +1330,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v8.0.6"
|
||||
"source": "https://github.com/symfony/console/tree/v8.0.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1350,7 +1350,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-25T16:59:43+00:00"
|
||||
"time": "2026-03-06T14:06:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
|
||||
@@ -14,10 +14,6 @@ parameters:
|
||||
enabled: false
|
||||
noNullableReturnTypeDeclaration:
|
||||
enabled: false
|
||||
privateInFinalClass:
|
||||
enabled: false
|
||||
noIsset:
|
||||
enabled: false
|
||||
finalInAbstractClass:
|
||||
enabled: false
|
||||
noConstructorParameterWithDefaultValue:
|
||||
@@ -38,50 +34,18 @@ parameters:
|
||||
reportUnmatchedIgnoredErrors: true
|
||||
ignoreErrors:
|
||||
# these are actually interesting but not right now:
|
||||
- identifier: staticMethod.dynamicCall
|
||||
- identifier: argument.templateType
|
||||
- identifier: method.childReturnType
|
||||
- identifier: instanceof.alwaysFalse
|
||||
- identifier: deadCode.unreachable
|
||||
- identifier: method.dynamicName
|
||||
- identifier: larastan.noEnvCallsOutsideOfConfig
|
||||
- identifier: property.notFound
|
||||
- identifier: arguments.count
|
||||
- identifier: staticMethod.dynamicName
|
||||
- identifier: catch.neverThrown
|
||||
- identifier: notIdentical.alwaysTrue
|
||||
- identifier: method.notFound
|
||||
- identifier: nullsafe.neverNull
|
||||
- identifier: identical.alwaysFalse
|
||||
- identifier: if.condNotBoolean
|
||||
# - identifier: booleanNot.exprNotBoolean
|
||||
- identifier: method.nonObject
|
||||
- identifier: function.impossibleType
|
||||
- identifier: booleanNot.exprNotBoolean
|
||||
- identifier: ternary.condNotBoolean
|
||||
- identifier: booleanNot.alwaysFalse
|
||||
- identifier: booleanAnd.alwaysFalse
|
||||
- identifier: greater.alwaysTrue
|
||||
- identifier: function.alreadyNarrowedType
|
||||
- identifier: booleanNot.alwaysTrue
|
||||
- identifier: property.phpDocType
|
||||
- identifier: nullCoalesce.offset
|
||||
- identifier: nullCoalesce.variable
|
||||
- identifier: larastan.noUnnecessaryCollectionCall
|
||||
- identifier: varTag.differentVariable
|
||||
- identifier: identical.alwaysTrue
|
||||
- identifier: clone.nonObject
|
||||
- identifier: assign.propertyReadOnly
|
||||
- identifier: property.nonObject
|
||||
- identifier: varTag.nativeType
|
||||
- identifier: booleanAnd.leftAlwaysFalse
|
||||
- identifier: property.onlyWritten
|
||||
- identifier: parameter.phpDocType
|
||||
- identifier: property.dynamicName
|
||||
- identifier: property.unusedType
|
||||
- identifier: staticMethod.deprecated
|
||||
- identifier: greater.invalid
|
||||
- identifier: instanceof.alwaysTrue
|
||||
# ignore everything but things that BREAK
|
||||
- identifier: property.deprecated
|
||||
- identifier: method.deprecated
|
||||
@@ -93,7 +57,15 @@ parameters:
|
||||
- identifier: assign.propertyType
|
||||
- identifier: return.unusedType
|
||||
- identifier: return.phpDocType
|
||||
# all errors below I will never fix.
|
||||
# all errors below I will (probably) never fix.
|
||||
- identifier: method.notFound # way too many false positives
|
||||
- identifier: catch.neverThrown # plenty of errors that are thrown undocumented
|
||||
- identifier: staticMethod.dynamicName # dont care
|
||||
- identifier: arguments.count # one false positive
|
||||
- identifier: property.notFound # false positives
|
||||
- identifier: method.dynamicName # i dont care
|
||||
- identifier: staticMethod.dynamicCall # many false positives.
|
||||
- identifier: argument.templateType # no clue how to fix single occurrence.
|
||||
# - '#expects view-string\|null, string given#'
|
||||
# - '#expects view-string, string given#'
|
||||
# - "#Parameter \\#[1-2] \\$num[1-2] of function bc[a-z]+ expects numeric-string, [a-z\\-|&]+ given#"
|
||||
|
||||
@@ -63,6 +63,8 @@ abstract class Controller extends BaseController
|
||||
use ValidatesRequests;
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
protected array $acceptedRoles = [];
|
||||
|
||||
protected const string CONTENT_TYPE = 'application/vnd.api+json';
|
||||
protected const string JSON_CONTENT_TYPE = 'application/json';
|
||||
|
||||
|
||||
@@ -112,19 +112,6 @@ final class BasicController extends Controller
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if date is outside session range.
|
||||
*/
|
||||
protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool
|
||||
{ // Validate a preference
|
||||
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// start and end in the past? use $end
|
||||
return $start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date);
|
||||
}
|
||||
|
||||
private function getBalanceInformation(Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug('getBalanceInformation');
|
||||
|
||||
@@ -62,7 +62,7 @@ final class BatchController extends Controller
|
||||
}
|
||||
Log::debug(sprintf('Counted %d journals.', count($journals)));
|
||||
|
||||
/** @var TransactionJournal $first */
|
||||
/** @var null|TransactionJournal $first */
|
||||
$first = $journals->first();
|
||||
$group = $first?->transactionGroup;
|
||||
if (null === $group) {
|
||||
|
||||
@@ -34,7 +34,9 @@ abstract class AggregateFormRequest extends ApiRequest
|
||||
/**
|
||||
* @var ApiRequest[]
|
||||
*/
|
||||
protected array $requests = [];
|
||||
protected array $requests = [];
|
||||
|
||||
protected array $acceptedRoles = [];
|
||||
|
||||
#[Override]
|
||||
public function initialize(
|
||||
|
||||
@@ -38,7 +38,7 @@ class DateRangeRequest extends ApiRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
$start = $this->getCarbonDate('start')?->startOfDay();
|
||||
|
||||
@@ -36,7 +36,7 @@ class DateRequest extends ApiRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
$date = $this->getCarbonDate('date')?->endOfDay();
|
||||
|
||||
@@ -50,7 +50,7 @@ class ObjectTypeApiRequest extends ApiRequest
|
||||
|
||||
$this->objectType = $config['object_type'] ?? null;
|
||||
|
||||
if (!$this->objectType) {
|
||||
if (null === $this->objectType) {
|
||||
throw new RuntimeException('ObjectTypeApiRequest requires a object_type config');
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class ObjectTypeApiRequest extends ApiRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
$type = $this->convertString('types', 'all');
|
||||
|
||||
@@ -42,7 +42,7 @@ class QueryRequest extends ApiRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
$query = $this->convertString('query');
|
||||
|
||||
@@ -40,7 +40,7 @@ class AccountTypeApiRequest extends ApiRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class AccountTypesApiRequest extends ApiRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
$types = explode(',', $this->convertString('types', 'all'));
|
||||
|
||||
@@ -40,6 +40,8 @@ class Request extends FormRequest
|
||||
use ChecksLogin;
|
||||
use ConvertsDataTypes;
|
||||
|
||||
protected array $acceptedRoles = [];
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Factory\TransactionCurrencyFactory;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
@@ -85,6 +86,7 @@ class StoreRequest extends FormRequest
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
/** @var Budget $budget */
|
||||
$budget = $this->route()->parameter('budget');
|
||||
$validator->after(static function (Validator $validator) use ($budget): void {
|
||||
if (0 !== count($validator->failed())) {
|
||||
|
||||
@@ -61,7 +61,7 @@ class UpdateRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
/** @var TransactionCurrency $currency */
|
||||
/** @var string|TransactionCurrency $currency */
|
||||
$currency = $this->route()->parameter('currency_code');
|
||||
if (is_string($currency)) {
|
||||
$currency = TransactionCurrency::whereCode($currency)->first();
|
||||
|
||||
@@ -41,7 +41,7 @@ class PaginationRequest extends ApiRequest
|
||||
|
||||
$this->sortClass = $config['sort_class'] ?? null;
|
||||
|
||||
if (!$this->sortClass) {
|
||||
if (null === $this->sortClass) {
|
||||
throw new RuntimeException('PaginationRequest requires a sort_class config');
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ class PaginationRequest extends ApiRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class PaginationRequest extends ApiRequest
|
||||
$page = $this->convertInteger('page');
|
||||
$page = min(max(1, $page), 2 ** 16);
|
||||
$offset = ($page - 1) * $limit;
|
||||
$sort = $this->sortClass ? $this->convertSortParameters('sort', $this->sortClass) : $this->get('sort');
|
||||
$sort = null !== $this->sortClass ? $this->convertSortParameters('sort', $this->sortClass) : $this->get('sort');
|
||||
$this->attributes->set('limit', $limit);
|
||||
$this->attributes->set('sort', $sort);
|
||||
$this->attributes->set('page', $page);
|
||||
|
||||
@@ -45,7 +45,7 @@ class CountRequest extends AggregateFormRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
$this->attributes->set('include_deleted', $this->convertBoolean($this->input('include_deleted', 'false')));
|
||||
|
||||
@@ -37,7 +37,7 @@ class SearchQueryRequest extends ApiRequest
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(function (Validator $validator): void {
|
||||
if ($validator->failed()) {
|
||||
if (count($validator->failed()) > 0) {
|
||||
return;
|
||||
}
|
||||
$query = $this->convertString('query');
|
||||
|
||||
@@ -57,24 +57,28 @@ class CorrectsIbans extends Command
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$userId = $account->user_id;
|
||||
$userId = $account->user_id;
|
||||
$set[$userId] ??= [];
|
||||
$iban = (string) $account->iban;
|
||||
$iban = (string) $account->iban;
|
||||
if ('' === $iban) {
|
||||
continue;
|
||||
}
|
||||
$type = $account->accountType->type;
|
||||
$type = $account->accountType->type;
|
||||
if (in_array($type, [AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value], true)) {
|
||||
$type = 'liabilities';
|
||||
}
|
||||
// iban already in use! two exceptions exist:
|
||||
if (
|
||||
array_key_exists($iban, $set[$userId]) && (
|
||||
!AccountTypeEnum::EXPENSE->value === $set[$userId][$iban]
|
||||
&& AccountTypeEnum::REVENUE->value === $type
|
||||
&& !(AccountTypeEnum::REVENUE->value === $set[$userId][$iban] && AccountTypeEnum::EXPENSE->value === $type)
|
||||
)
|
||||
) {
|
||||
$showWarningAndCorrect = false;
|
||||
if (array_key_exists($iban, $set[$userId])) {
|
||||
// the type is a revenue account, and the existing IBAN is NOT an expense account.
|
||||
if (AccountTypeEnum::REVENUE->value === $type && AccountTypeEnum::EXPENSE->value !== $set[$userId][$iban]) {
|
||||
$showWarningAndCorrect = true;
|
||||
}
|
||||
// the type is an expense account, and the existing IBAN is NOT a revenue account
|
||||
if (AccountTypeEnum::EXPENSE->value === $type && AccountTypeEnum::REVENUE->value !== $set[$userId][$iban]) {
|
||||
$showWarningAndCorrect = true;
|
||||
}
|
||||
}
|
||||
if ($showWarningAndCorrect) {
|
||||
$this->friendlyWarning(sprintf(
|
||||
'IBAN "%s" is used more than once and will be removed from %s #%d ("%s")',
|
||||
$iban,
|
||||
|
||||
@@ -69,10 +69,6 @@ class CorrectsInvertedBudgetLimits extends Command
|
||||
$budgetLimit->saveQuietly();
|
||||
}
|
||||
|
||||
if ($set->count() > 0) {
|
||||
// FIXME here be a available budget event.
|
||||
}
|
||||
|
||||
if (1 === $set->count()) {
|
||||
$this->friendlyInfo('Corrected one budget limit to have the right start/end dates.');
|
||||
|
||||
|
||||
@@ -322,7 +322,7 @@ class CorrectsUnevenAmount extends Command
|
||||
foreach ($journals as $entry) {
|
||||
$sum = (string) $entry->the_sum;
|
||||
$sum = Steam::floatalize($sum);
|
||||
if (!is_numeric($sum) || '' === $sum || str_contains($sum, 'e') || str_contains($sum, ',')) {
|
||||
if (!is_numeric($sum) || str_contains($sum, 'e') || str_contains($sum, ',')) {
|
||||
$message = sprintf('Journal #%d has an invalid sum ("%s"). No sure what to do.', $entry->transaction_journal_id, $entry->the_sum);
|
||||
$this->friendlyWarning($message);
|
||||
Log::warning($message);
|
||||
|
||||
@@ -127,7 +127,7 @@ class RemovesDatabaseDecryption extends Command
|
||||
}
|
||||
|
||||
// A separate routine for preferences table:
|
||||
if ('preferences' === $table && is_string($value)) {
|
||||
if ('preferences' === $table) {
|
||||
$this->decryptPreferencesRow($id, $value);
|
||||
|
||||
return;
|
||||
|
||||
@@ -101,8 +101,13 @@ class UpgradesLiabilitiesEight extends Command
|
||||
|
||||
private function hasBadOpening(Account $account): bool
|
||||
{
|
||||
/** @var TransactionType $openingBalanceType */
|
||||
$openingBalanceType = TransactionType::whereType(TransactionTypeEnum::OPENING_BALANCE->value)->first();
|
||||
|
||||
/** @var TransactionType $liabilityType */
|
||||
$liabilityType = TransactionType::whereType(TransactionTypeEnum::LIABILITY_CREDIT->value)->first();
|
||||
|
||||
/** @var null|TransactionJournal $openingJournal */
|
||||
$openingJournal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $account->id)
|
||||
->where('transaction_journals.transaction_type_id', $openingBalanceType->id)
|
||||
@@ -111,6 +116,8 @@ class UpgradesLiabilitiesEight extends Command
|
||||
if (null === $openingJournal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var null|TransactionJournal $liabilityJournal */
|
||||
$liabilityJournal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $account->id)
|
||||
->where('transaction_journals.transaction_type_id', $liabilityType->id)
|
||||
@@ -120,7 +127,7 @@ class UpgradesLiabilitiesEight extends Command
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $openingJournal->date->isSameDay($liabilityJournal->date);
|
||||
return $openingJournal->date->isSameDay($liabilityJournal->date);
|
||||
}
|
||||
|
||||
private function isExecuted(): bool
|
||||
|
||||
@@ -36,7 +36,7 @@ final class IntervalException extends Exception
|
||||
public array $availableIntervals = [];
|
||||
public Periodicity $periodicity = Periodicity::Monthly;
|
||||
|
||||
/** @var mixed */
|
||||
/** @var string */
|
||||
protected $message = 'The periodicity %s is unknown. Choose one of available periodicity: %s';
|
||||
|
||||
public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null)
|
||||
|
||||
@@ -338,7 +338,7 @@ class TransactionJournalFactory
|
||||
'date_tz' => $carbon->format('e'),
|
||||
'order' => $order,
|
||||
'tag_count' => 0,
|
||||
'completed' => !$row['batch_submission'],
|
||||
'completed' => is_bool($row['batch_submission']) && !$row['batch_submission'],
|
||||
]);
|
||||
Log::debug(sprintf('Created new journal #%d: "%s"', $journal->id, $journal->description));
|
||||
|
||||
@@ -574,16 +574,11 @@ class TransactionJournalFactory
|
||||
return [$sourceAccount, $account];
|
||||
}
|
||||
|
||||
if (!$sourceAccount instanceof Account) {
|
||||
Log::debug('Source account is NULL, destination account is not.');
|
||||
$account = $this->accountRepository->getReconciliation($destinationAccount);
|
||||
Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type));
|
||||
Log::debug('Source account is NULL, destination account is not.');
|
||||
$account = $this->accountRepository->getReconciliation($destinationAccount);
|
||||
Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type));
|
||||
|
||||
return [$account, $destinationAccount];
|
||||
}
|
||||
Log::debug('Unused fallback');
|
||||
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
return [$account, $destinationAccount];
|
||||
}
|
||||
|
||||
private function storeLocation(TransactionJournal $journal, NullArrayObject $data): void
|
||||
|
||||
@@ -275,7 +275,7 @@ final class LoginController extends Controller
|
||||
$request->session()->regenerate();
|
||||
$this->clearLoginAttempts($request);
|
||||
$response = $this->authenticated($request, $this->guard()->user());
|
||||
if ($response) {
|
||||
if (null !== $response) {
|
||||
return $response;
|
||||
}
|
||||
$path = Steam::getSafeUrl(session()->pull('url.intended', route('index')), route('index'));
|
||||
|
||||
@@ -176,7 +176,7 @@ final class RegisterController extends Controller
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
protected function allowedToRegister(): bool
|
||||
private function allowedToRegister(): bool
|
||||
{
|
||||
// is allowed to register?
|
||||
$allowRegistration = true;
|
||||
|
||||
@@ -304,7 +304,7 @@ final class DebugController extends Controller
|
||||
|
||||
return [
|
||||
'debug' => var_export(config('app.debug'), true),
|
||||
'audit_log_channel' => envNonEmpty('AUDIT_LOG_CHANNEL', '(empty)'),
|
||||
'audit_log_channel' => implode(', ', config('logging.channels.audit.channels')),
|
||||
'default_language' => (string) config('firefly.default_language'),
|
||||
'default_locale' => (string) config('firefly.default_locale'),
|
||||
'remote_header' => 'remote_user_guard' === $userGuard ? config('auth.guard_header') : 'N/A',
|
||||
@@ -323,11 +323,11 @@ final class DebugController extends Controller
|
||||
private function getBuildInfo(): array
|
||||
{
|
||||
$return = [
|
||||
'is_docker' => env('IS_DOCKER', false),
|
||||
'is_docker' => config('firefly.is_docker'),
|
||||
'build' => '(unknown)',
|
||||
'build_date' => '(unknown)',
|
||||
'base_build' => '(unknown)',
|
||||
'base_build_date' => '(unknown)',
|
||||
'base_build' => config('firefly.base_image_build'),
|
||||
'base_build_date' => config('firefly.base_image_date'),
|
||||
];
|
||||
|
||||
try {
|
||||
@@ -348,12 +348,6 @@ final class DebugController extends Controller
|
||||
Log::debug('Could not check build date, but thats ok.');
|
||||
Log::warning($e->getMessage());
|
||||
}
|
||||
if ('' !== (string) env('BASE_IMAGE_BUILD')) {
|
||||
$return['base_build'] = env('BASE_IMAGE_BUILD');
|
||||
}
|
||||
if ('' !== (string) env('BASE_IMAGE_DATE')) {
|
||||
$return['base_build_date'] = env('BASE_IMAGE_DATE');
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ final class PreferencesController extends Controller
|
||||
AccountTypeEnum::DEBT->value,
|
||||
AccountTypeEnum::MORTGAGE->value,
|
||||
]);
|
||||
$isDocker = env('IS_DOCKER', false);
|
||||
$isDocker = config('firefly.is_docker');
|
||||
$groupedAccounts = [];
|
||||
|
||||
/** @var Account $account */
|
||||
|
||||
@@ -67,7 +67,7 @@ class SecureHeaders
|
||||
];
|
||||
|
||||
// overrule in development mode
|
||||
if (true === env('IS_LOCAL_DEV')) {
|
||||
if (true === config('firefly.is_local_dev')) {
|
||||
$csp = [
|
||||
"default-src 'none'",
|
||||
"object-src 'none'",
|
||||
|
||||
@@ -213,7 +213,7 @@ class CreateRecurringTransactions implements ShouldQueue
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$single = [
|
||||
'type' => null === $transaction?->transactionType?->type
|
||||
'type' => null === $transaction->transactionType?->type
|
||||
? strtolower((string) $recurrence->transactionType->type)
|
||||
: strtolower($transaction->transactionType->type),
|
||||
'date' => $date,
|
||||
|
||||
@@ -42,7 +42,7 @@ class ProcessesBudgetLimits implements ShouldQueue
|
||||
public function handle(CreatedBudgetLimit|DestroyedBudgetLimit|UpdatedBudgetLimit $event): void
|
||||
{
|
||||
Log::debug(sprintf('Now in ProcessesBudgetLimits::handle for event %s', get_class($event)));
|
||||
if ($event instanceof DestroyedBudgetLimit && null !== $event->user) {
|
||||
if ($event instanceof DestroyedBudgetLimit) {
|
||||
// need to recalculate all available budgets for this user.
|
||||
$calculator = new AvailableBudgetCalculator();
|
||||
$calculator->setUser($event->user);
|
||||
|
||||
@@ -58,10 +58,10 @@ class SendsWebhookMessages implements ShouldQueue
|
||||
$message->save();
|
||||
Log::debug(sprintf('Send message #%d', $message->id));
|
||||
SendWebhookMessage::dispatch($message)->afterResponse();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (false !== $message->sent) {
|
||||
Log::debug(sprintf('Skip message #%d', $message->id));
|
||||
}
|
||||
Log::debug(sprintf('Skip message #%d', $message->id));
|
||||
}
|
||||
|
||||
// clean up sent messages table:
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Handlers\Observer\BillObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
@@ -38,6 +39,11 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* @property Carbon $date
|
||||
* @property null|Carbon $end_date
|
||||
* @property null|Carbon $extension_date
|
||||
*/
|
||||
#[ObservedBy([BillObserver::class])]
|
||||
class Bill extends Model
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
@@ -32,6 +33,9 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* @property Carbon $date
|
||||
*/
|
||||
class CurrencyExchangeRate extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
@@ -11,6 +12,10 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
/**
|
||||
* @property Carbon $start
|
||||
* @property Carbon $end
|
||||
*/
|
||||
class PeriodStatistic extends Model
|
||||
{
|
||||
use ReturnsIntegerUserIdTrait;
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Handlers\Observer\PiggyBankObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
@@ -36,6 +37,10 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* @property null|Carbon $target_date
|
||||
* @property null|Carbon $start_date
|
||||
*/
|
||||
#[ObservedBy([PiggyBankObserver::class])]
|
||||
class PiggyBank extends Model
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Handlers\Observer\PiggyBankEventObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
@@ -31,6 +32,9 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @property Carbon $date
|
||||
*/
|
||||
#[ObservedBy([PiggyBankEventObserver::class])]
|
||||
class PiggyBankEvent extends Model
|
||||
{
|
||||
|
||||
@@ -30,6 +30,9 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* @property mixed $data
|
||||
*/
|
||||
class Preference extends Model
|
||||
{
|
||||
use ReturnsIntegerIdTrait;
|
||||
|
||||
@@ -40,8 +40,9 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* @property Carbon $first_date
|
||||
* @property null|Carbon $first_date
|
||||
* @property null|Carbon $latest_date
|
||||
* @property null|Carbon $repeat_until
|
||||
*/
|
||||
#[ObservedBy([DeletedRecurrenceObserver::class])]
|
||||
class Recurrence extends Model
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Casts\SeparateTimezoneCaster;
|
||||
use FireflyIII\Handlers\Observer\DeletedTagObserver;
|
||||
use FireflyIII\Support\Models\ReturnsIntegerIdTrait;
|
||||
@@ -36,6 +37,9 @@ use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* @property null|Carbon $date
|
||||
*/
|
||||
#[ObservedBy([DeletedTagObserver::class])]
|
||||
class Tag extends Model
|
||||
{
|
||||
|
||||
@@ -47,7 +47,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
* @method EloquentBuilder|static after()
|
||||
* @method static EloquentBuilder|static query()
|
||||
*
|
||||
* @property TransactionGroup $transactionGroup
|
||||
* @property null|TransactionGroup $transactionGroup
|
||||
* @property Carbon $date
|
||||
*/
|
||||
#[ObservedBy([DeletedTransactionJournalObserver::class])]
|
||||
class TransactionJournal extends Model
|
||||
|
||||
@@ -687,6 +687,31 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
|
||||
return $dbQuery->take($limit)->get(['accounts.*']);
|
||||
}
|
||||
|
||||
public function searchAccountIncludingInactive(string $query, array $types, int $limit): Collection
|
||||
{
|
||||
$dbQuery = $this->user
|
||||
->accounts()
|
||||
->orderBy('accounts.order', 'ASC')
|
||||
->orderBy('accounts.account_type_id', 'ASC')
|
||||
->orderBy('accounts.name', 'ASC')
|
||||
->with(['accountType'])
|
||||
;
|
||||
if ('' !== $query) {
|
||||
// split query on spaces just in case:
|
||||
$parts = explode(' ', $query);
|
||||
foreach ($parts as $part) {
|
||||
$search = sprintf('%%%s%%', $part);
|
||||
$dbQuery->whereLike('name', $search);
|
||||
}
|
||||
}
|
||||
if (0 !== count($types)) {
|
||||
$dbQuery->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
$dbQuery->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
return $dbQuery->take($limit)->get(['accounts.*']);
|
||||
}
|
||||
|
||||
public function searchAccountNr(string $query, array $types, int $limit): Collection
|
||||
{
|
||||
$dbQuery = $this->user
|
||||
|
||||
@@ -156,6 +156,8 @@ interface AccountRepositoryInterface
|
||||
|
||||
public function searchAccount(string $query, array $types, int $limit): Collection;
|
||||
|
||||
public function searchAccountIncludingInactive(string $query, array $types, int $limit): Collection;
|
||||
|
||||
public function searchAccountNr(string $query, array $types, int $limit): Collection;
|
||||
|
||||
public function store(array $data): Account;
|
||||
|
||||
@@ -389,17 +389,13 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
|
||||
return (string) $budgetLimit->amount;
|
||||
}
|
||||
// if budget limit period is inside AB period, it can be added in full.
|
||||
if (!$limitPeriod->equals($availableBudgetPeriod) && $availableBudgetPeriod->contains($limitPeriod)) {
|
||||
if ($availableBudgetPeriod->contains($limitPeriod)) {
|
||||
Log::debug('This budget limit is smaller than the available budget period.');
|
||||
|
||||
return (string) $budgetLimit->amount;
|
||||
}
|
||||
|
||||
if (
|
||||
!$limitPeriod->equals($availableBudgetPeriod)
|
||||
&& !$availableBudgetPeriod->contains($limitPeriod)
|
||||
&& $availableBudgetPeriod->overlapsWith($limitPeriod)
|
||||
) {
|
||||
if ($availableBudgetPeriod->overlapsWith($limitPeriod)) {
|
||||
Log::debug('This budget limit is something else entirely!');
|
||||
$overlap = $availableBudgetPeriod->overlap($limitPeriod);
|
||||
if ($overlap instanceof Period) {
|
||||
|
||||
@@ -101,8 +101,12 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
'currency_code' => (string) $journal['currency_code'],
|
||||
'currency_decimal_places' => (int) $journal['currency_decimal_places'],
|
||||
'foreign_currency_id' => (int) ($journal['foreign_currency_id'] ?? 0),
|
||||
'foreign_amount' => isset($journal['foreign_amount']) ? Steam::negative((string) $journal['foreign_amount']) : null,
|
||||
'pc_amount' => isset($journal['pc_amount']) ? Steam::negative((string) $journal['pc_amount']) : null,
|
||||
'foreign_amount' => array_key_exists('foreign_amount', $journal) && null !== $journal['foreign_amount']
|
||||
? Steam::negative((string) $journal['foreign_amount'])
|
||||
: null,
|
||||
'pc_amount' => array_key_exists('pc_amount', $journal) && null !== $journal['pc_amount']
|
||||
? Steam::negative((string) $journal['pc_amount'])
|
||||
: null,
|
||||
'date' => $journal['date'],
|
||||
'source_account_id' => $journal['source_account_id'],
|
||||
'budget_name' => $journal['budget_name'],
|
||||
@@ -186,8 +190,12 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
'currency_code' => (string) $journal['currency_code'],
|
||||
'currency_decimal_places' => (int) $journal['currency_decimal_places'],
|
||||
'foreign_currency_id' => (int) ($journal['foreign_currency_id'] ?? 0),
|
||||
'foreign_amount' => isset($journal['foreign_amount']) ? Steam::positive((string) $journal['foreign_amount']) : null,
|
||||
'pc_amount' => isset($journal['pc_amount']) ? Steam::positive((string) $journal['pc_amount']) : null,
|
||||
'foreign_amount' => array_key_exists('foreign_amount', $journal) && null !== $journal['foreign_amount']
|
||||
? Steam::positive((string) $journal['foreign_amount'])
|
||||
: null,
|
||||
'pc_amount' => array_key_exists('pc_amount', $journal) && null !== $journal['pc_amount']
|
||||
? Steam::positive((string) $journal['pc_amount'])
|
||||
: null,
|
||||
'date' => $journal['date'],
|
||||
'source_account_id' => $journal['source_account_id'],
|
||||
'budget_name' => $journal['budget_name'],
|
||||
|
||||
@@ -253,10 +253,7 @@ class UserGroupRepository implements UserGroupRepositoryInterface, UserGroupInte
|
||||
// group has multiple members. How many are owner, except the user we're editing now?
|
||||
$ownerCount = $userGroup->groupMemberships()->where('user_role_id', $owner->id)->where('user_id', '!=', $user->id)->count();
|
||||
// if there are no other owners and the current users does not get or keep the owner role, refuse.
|
||||
if (
|
||||
0 === $ownerCount
|
||||
&& (0 === count($data['roles']) || count($data['roles']) > 0 && !in_array(UserRoleEnum::OWNER->value, $data['roles'], true))
|
||||
) {
|
||||
if (0 === $ownerCount && (0 === count($data['roles']) || !in_array(UserRoleEnum::OWNER->value, $data['roles'], true))) {
|
||||
Log::debug('User needs to keep owner role in this group, refuse to act');
|
||||
|
||||
throw new FireflyException('The last owner in this user group must keep the "owner" role.');
|
||||
|
||||
@@ -41,9 +41,6 @@ class IsValidAccountTypeList implements ValidationRule
|
||||
if (is_string($value)) {
|
||||
$values = explode(',', $value);
|
||||
}
|
||||
if (!is_array($values)) {
|
||||
$fail('validation.invalid_account_list')->translate();
|
||||
}
|
||||
$keys = array_keys($this->types);
|
||||
foreach ($values as $entry) {
|
||||
if (!in_array($entry, $keys, true)) {
|
||||
|
||||
@@ -41,9 +41,6 @@ class IsValidTransactionTypeList implements ValidationRule
|
||||
if (is_string($value)) {
|
||||
$values = explode(',', $value);
|
||||
}
|
||||
if (!is_array($values)) {
|
||||
$fail('validation.invalid_transaction_type_list')->translate();
|
||||
}
|
||||
$keys = array_keys($this->transactionTypes);
|
||||
foreach ($values as $entry) {
|
||||
if (!in_array($entry, $keys, true)) {
|
||||
|
||||
@@ -86,6 +86,8 @@ class AccountDestroyService
|
||||
foreach ($collection as $row) {
|
||||
if ((int) $row->the_count > 1) {
|
||||
$journalId = $row->transaction_journal_id;
|
||||
|
||||
/** @var null|TransactionJournal $journal */
|
||||
$journal = $user->transactionJournals()->find($journalId);
|
||||
if (null !== $journal) {
|
||||
Log::debug(sprintf('Deleted journal #%d because it has the same source as destination.', $journal->id));
|
||||
|
||||
@@ -144,15 +144,17 @@ class RemoteUserGuard implements Guard
|
||||
return $this->user?->id;
|
||||
}
|
||||
|
||||
public function setUser(Authenticatable|User|null $user): void
|
||||
public function setUser(Authenticatable|User|null $user): Guard
|
||||
{
|
||||
// Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
|
||||
return;
|
||||
return $this;
|
||||
}
|
||||
Log::error(sprintf('Did not set user at %s', __METHOD__));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function user(): ?User
|
||||
|
||||
@@ -43,14 +43,12 @@ class BudgetList implements BinderInterface
|
||||
if ('allBudgets' === $value) {
|
||||
return auth()->user()->budgets()->where('active', true)->orderBy('order', 'ASC')->orderBy('name', 'ASC')->get();
|
||||
}
|
||||
|
||||
$list = array_unique(array_map(\intval(...), explode(',', $value)));
|
||||
|
||||
if (0 === count($list)) {
|
||||
if ('' === $value) {
|
||||
Log::warning('Budget list count is zero, return 404.');
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$list = array_unique(array_map(\intval(...), explode(',', $value)));
|
||||
|
||||
/** @var Collection $collection */
|
||||
$collection = auth()->user()->budgets()->where('active', true)->whereIn('id', $list)->get();
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Support\Binder;
|
||||
use FireflyIII\Models\Category;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
@@ -42,11 +43,12 @@ class CategoryList implements BinderInterface
|
||||
if ('allCategories' === $value) {
|
||||
return auth()->user()->categories()->orderBy('name', 'ASC')->get();
|
||||
}
|
||||
if ('' === $value) {
|
||||
Log::warning('Category list count is zero, return 404.');
|
||||
|
||||
$list = array_unique(array_map(\intval(...), explode(',', $value)));
|
||||
if (0 === count($list)) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$list = array_unique(array_map(\intval(...), explode(',', $value)));
|
||||
|
||||
/** @var Collection $collection */
|
||||
$collection = auth()->user()->categories()->whereIn('id', $list)->get();
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Support\Binder;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
@@ -65,11 +66,12 @@ class JournalList implements BinderInterface
|
||||
|
||||
protected static function parseList(string $value): array
|
||||
{
|
||||
$list = array_unique(array_map(\intval(...), explode(',', $value)));
|
||||
if (0 === count($list)) {
|
||||
if ('' === $value) {
|
||||
Log::warning('Category list count is zero, return 404.');
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
return $list;
|
||||
return array_unique(array_map(\intval(...), explode(',', $value)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,15 +44,15 @@ class TagList implements BinderInterface
|
||||
if ('allTags' === $value) {
|
||||
return auth()->user()->tags()->orderBy('tag', 'ASC')->get();
|
||||
}
|
||||
$list = array_unique(array_map(\strtolower(...), explode(',', $value)));
|
||||
Log::debug('List of tags is', $list);
|
||||
|
||||
if (0 === count($list)) {
|
||||
Log::error('Tag list is empty.');
|
||||
if ('' === $value) {
|
||||
Log::warning('Category list count is zero, return 404.');
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
$list = array_unique(array_map(\strtolower(...), explode(',', $value)));
|
||||
Log::debug('List of tags is', $list);
|
||||
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
|
||||
@@ -89,16 +89,15 @@ trait ValidatesUserGroupTrait
|
||||
throw new AuthorizationException((string) trans('validation.belongs_user_or_user_group'));
|
||||
}
|
||||
Log::debug(sprintf('validateUserGroup: validate access of user to group #%d ("%s").', $groupId, $group->title));
|
||||
$roles = property_exists($this, 'acceptedRoles') ? $this->acceptedRoles : [];
|
||||
if (0 === count($roles)) {
|
||||
if (0 === count($this->acceptedRoles)) {
|
||||
Log::debug('validateUserGroup: no roles defined, so no access.');
|
||||
|
||||
throw new AuthorizationException((string) trans('validation.no_accepted_roles_defined'));
|
||||
}
|
||||
Log::debug(sprintf('validateUserGroup: have %d roles to check.', count($roles)), $roles);
|
||||
Log::debug(sprintf('validateUserGroup: have %d roles to check.', count($this->acceptedRoles)), $this->acceptedRoles);
|
||||
|
||||
/** @var UserRoleEnum $role */
|
||||
foreach ($roles as $role) {
|
||||
foreach ($this->acceptedRoles as $role) {
|
||||
if ($user->hasRoleInGroupOrOwner($group, $role)) {
|
||||
Log::debug(sprintf('validateUserGroup: User has role "%s" in group #%d, return the group.', $role->value, $groupId));
|
||||
$this->userGroup = $group;
|
||||
|
||||
@@ -128,6 +128,12 @@ class BillDateCalculator
|
||||
}
|
||||
}
|
||||
Log::debug('end of loop');
|
||||
|
||||
/** @template T
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return null|T
|
||||
*/
|
||||
$simple = $set->map(static fn (Carbon $date) => $date->format('Y-m-d'));
|
||||
Log::debug(sprintf('Found %d pay dates', $set->count()), $simple->toArray());
|
||||
|
||||
|
||||
@@ -201,25 +201,25 @@ class Navigation
|
||||
Log::debug('endOfPeriod() requests "YTD" + future, set it to "3M" instead.');
|
||||
$repeatFreq = '3M';
|
||||
}
|
||||
|
||||
$new = Carbon::now();
|
||||
$functionMap = [
|
||||
'1D' => 'endOfDay',
|
||||
'daily' => 'endOfDay',
|
||||
'1W' => 'addWeek',
|
||||
'week' => 'addWeek',
|
||||
'weekly' => 'addWeek',
|
||||
'1M' => 'addMonth',
|
||||
'month' => 'addMonth',
|
||||
'monthly' => 'addMonth',
|
||||
'3M' => 'addQuarter',
|
||||
'quarter' => 'addQuarter',
|
||||
'quarterly' => 'addQuarter',
|
||||
'1W' => 'addWeeks',
|
||||
'week' => 'addWeeks',
|
||||
'weekly' => 'addWeeks',
|
||||
'1M' => 'addMonths',
|
||||
'month' => 'addMonths',
|
||||
'monthly' => 'addMonths',
|
||||
'3M' => 'addQuarters',
|
||||
'quarter' => 'addQuarters',
|
||||
'quarterly' => 'addQuarters',
|
||||
'6M' => 'addMonths',
|
||||
'half-year' => 'addMonths',
|
||||
'half_year' => 'addMonths',
|
||||
'year' => 'addYear',
|
||||
'yearly' => 'addYear',
|
||||
'1Y' => 'addYear',
|
||||
'year' => 'addYears',
|
||||
'yearly' => 'addYears',
|
||||
'1Y' => 'addYears',
|
||||
];
|
||||
$modifierMap = ['half-year' => 6, 'half_year' => 6, '6M' => 6];
|
||||
$subDay = ['week', 'weekly', '1W', 'month', 'monthly', '1M', '3M', 'quarter', 'quarterly', '6M', 'half-year', 'half_year', '1Y', 'year', 'yearly'];
|
||||
|
||||
@@ -45,8 +45,8 @@ trait ChecksLogin
|
||||
if (!$check) {
|
||||
return false;
|
||||
}
|
||||
if (!property_exists($this, 'acceptedRoles')) {
|
||||
Log::debug(sprintf('Request class %s has no acceptedRoles array', static::class));
|
||||
if (0 === count($this->acceptedRoles)) {
|
||||
Log::debug(sprintf('Request class %s has 0 entries in acceptedRoles array', static::class));
|
||||
|
||||
return true; // check for false already took place.
|
||||
}
|
||||
|
||||
@@ -205,10 +205,9 @@ trait ConvertsDataTypes
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
|
||||
if (method_exists($this, 'validateUserGroup')) {
|
||||
$userGroup = $this->validateUserGroup($this);
|
||||
$repository->setUserGroup($userGroup);
|
||||
}
|
||||
// blindly assume this method exists.
|
||||
$userGroup = $this->validateUserGroup($this);
|
||||
$repository->setUserGroup($userGroup);
|
||||
|
||||
// set administration ID
|
||||
// group ID
|
||||
|
||||
@@ -487,7 +487,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
|
||||
// search direction: for destination accounts
|
||||
if (SearchDirection::DESTINATION === $searchDirection) { // destination
|
||||
// destination can be
|
||||
// the destination account can be
|
||||
$searchTypes = [
|
||||
AccountTypeEnum::ASSET->value,
|
||||
AccountTypeEnum::MORTGAGE->value,
|
||||
@@ -530,7 +530,7 @@ class OperatorQuerySearch implements SearchInterface
|
||||
}
|
||||
|
||||
// get accounts:
|
||||
$accounts = $this->accountRepository->searchAccount($value, $searchTypes, 1337);
|
||||
$accounts = $this->accountRepository->searchAccountIncludingInactive($value, $searchTypes, 1337);
|
||||
if (0 === $accounts->count() && false === $prohibited) {
|
||||
Log::warning('Found zero accounts, search for non existing account, NO results will be returned.');
|
||||
$this->collector->findNothing();
|
||||
|
||||
@@ -47,7 +47,6 @@ use Illuminate\Http\Middleware\HandleCors;
|
||||
use Illuminate\Http\Middleware\ValidatePostSize;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
use Laravel\Passport\Http\Middleware\CreateFreshApiToken;
|
||||
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
|
||||
use PragmaRX\Google2FALaravel\Middleware as MFAMiddleware;
|
||||
|
||||
/*
|
||||
@@ -63,19 +62,20 @@ use PragmaRX\Google2FALaravel\Middleware as MFAMiddleware;
|
||||
|
||||
bcscale(12);
|
||||
|
||||
if (!function_exists('envNonEmpty')) {
|
||||
if (!function_exists('envDefaultWhenEmpty')) {
|
||||
/**
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
function envNonEmpty(string $key, string | int | bool | null $default = null)
|
||||
function envDefaultWhenEmpty(mixed $value, string | int | bool | null $default = null): mixed
|
||||
{
|
||||
$result = env($key, $default);
|
||||
if ('' === $result) {
|
||||
if(null === $value) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $result;
|
||||
if('' === $value) {
|
||||
return $default;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
changelog.md
16
changelog.md
@@ -3,11 +3,11 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 6.5.4 - 2026-03-06
|
||||
## v6.5.4 - 2026-03-06
|
||||
|
||||
### Added
|
||||
|
||||
- Add some debug info to find
|
||||
- Add some debug info to find problems with available budget calculations.
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -17,13 +17,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
### Security
|
||||
|
||||
- Published security advisory https://github.com/firefly-iii/firefly-iii/security/advisories/GHSA-5q8v-j673-m5v4 found and reported by @lighthousekeeper1212
|
||||
- It's possible to submit webhook URLs that point to internal IP addresses. This will still be the case in the future, though some reserved ranges are no blocked. Let me know if this impacts you.
|
||||
- It's possible to submit webhook URLs that point to internal IP addresses. This will still be the case in the future, though some reserved ranges are now blocked. Let me know if this impacts you.
|
||||
|
||||
### API
|
||||
|
||||
- Initial release.
|
||||
|
||||
## 6.5.3 - 2026-03-05
|
||||
## v6.5.3 - 2026-03-05
|
||||
|
||||
This release fixes some sloppy coding on my part, but good news everyone! A new linter is in place that should prevent that from happening. Turns out I had disabled it in the past :(.
|
||||
|
||||
@@ -38,7 +34,7 @@ This release fixes some sloppy coding on my part, but good news everyone! A new
|
||||
### Fixed
|
||||
- [Issue 11866](https://github.com/firefly-iii/firefly-iii/issues/11866) (ReflectionException on Transaction\ListRequest) reported by @brot
|
||||
|
||||
## 6.5.2 - 2026-03-04
|
||||
## v6.5.2 - 2026-03-04
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -61,7 +57,7 @@ This release fixes some sloppy coding on my part, but good news everyone! A new
|
||||
- [Issue 11822](https://github.com/firefly-iii/firefly-iii/issues/11822) (API - account transaction type filtering) reported by @mgrove36
|
||||
- [Issue 11842](https://github.com/firefly-iii/firefly-iii/issues/11842) (API: `/api/v1/configuration` always returns unauthenticated for v6.5.1) reported by @dreautall
|
||||
|
||||
## 6.5.1 - 2026-02-28
|
||||
## v6.5.1 - 2026-02-28
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This releases also fixes a security issue, relevant only if you have multiple users using your Firefly III instance. Upgrading is recommended.
|
||||
|
||||
72
composer.lock
generated
72
composer.lock
generated
@@ -6366,16 +6366,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/cache",
|
||||
"version": "v8.0.6",
|
||||
"version": "v8.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/cache.git",
|
||||
"reference": "59184fa14658d7724cd9b8743d91c1b1aa618bff"
|
||||
"reference": "b7b0f4ce5fb57a8dc061d494639e44e2cf7aa30f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/cache/zipball/59184fa14658d7724cd9b8743d91c1b1aa618bff",
|
||||
"reference": "59184fa14658d7724cd9b8743d91c1b1aa618bff",
|
||||
"url": "https://api.github.com/repos/symfony/cache/zipball/b7b0f4ce5fb57a8dc061d494639e44e2cf7aa30f",
|
||||
"reference": "b7b0f4ce5fb57a8dc061d494639e44e2cf7aa30f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6442,7 +6442,7 @@
|
||||
"psr6"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/cache/tree/v8.0.6"
|
||||
"source": "https://github.com/symfony/cache/tree/v8.0.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6462,7 +6462,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-21T23:29:37+00:00"
|
||||
"time": "2026-03-06T13:17:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/cache-contracts",
|
||||
@@ -6619,16 +6619,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.4.6",
|
||||
"version": "v7.4.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "6d643a93b47398599124022eb24d97c153c12f27"
|
||||
"reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/6d643a93b47398599124022eb24d97c153c12f27",
|
||||
"reference": "6d643a93b47398599124022eb24d97c153c12f27",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d",
|
||||
"reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6693,7 +6693,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.4.6"
|
||||
"source": "https://github.com/symfony/console/tree/v7.4.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6713,7 +6713,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-25T17:02:47+00:00"
|
||||
"time": "2026-03-06T14:06:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
@@ -7231,16 +7231,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-client",
|
||||
"version": "v8.0.6",
|
||||
"version": "v8.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-client.git",
|
||||
"reference": "f425139487f904e198f99e3c416c79ed08cef3c3"
|
||||
"reference": "ade9bd433450382f0af154661fc8e72758b4de36"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-client/zipball/f425139487f904e198f99e3c416c79ed08cef3c3",
|
||||
"reference": "f425139487f904e198f99e3c416c79ed08cef3c3",
|
||||
"url": "https://api.github.com/repos/symfony/http-client/zipball/ade9bd433450382f0af154661fc8e72758b4de36",
|
||||
"reference": "ade9bd433450382f0af154661fc8e72758b4de36",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7303,7 +7303,7 @@
|
||||
"http"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-client/tree/v8.0.6"
|
||||
"source": "https://github.com/symfony/http-client/tree/v8.0.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7323,7 +7323,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-20T07:51:53+00:00"
|
||||
"time": "2026-03-06T13:17:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-client-contracts",
|
||||
@@ -7405,16 +7405,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v7.4.6",
|
||||
"version": "v7.4.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "fd97d5e926e988a363cef56fbbf88c5c528e9065"
|
||||
"reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/fd97d5e926e988a363cef56fbbf88c5c528e9065",
|
||||
"reference": "fd97d5e926e988a363cef56fbbf88c5c528e9065",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f94b3e7b7dafd40e666f0c9ff2084133bae41e81",
|
||||
"reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7463,7 +7463,7 @@
|
||||
"description": "Defines an object-oriented layer for the HTTP specification",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.4.6"
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.4.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7483,20 +7483,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-21T16:25:55+00:00"
|
||||
"time": "2026-03-06T13:15:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
"version": "v7.4.6",
|
||||
"version": "v7.4.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-kernel.git",
|
||||
"reference": "002ac0cf4cd972a7fd0912dcd513a95e8a81ce83"
|
||||
"reference": "3b3fcf386c809be990c922e10e4c620d6367cab1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/002ac0cf4cd972a7fd0912dcd513a95e8a81ce83",
|
||||
"reference": "002ac0cf4cd972a7fd0912dcd513a95e8a81ce83",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/3b3fcf386c809be990c922e10e4c620d6367cab1",
|
||||
"reference": "3b3fcf386c809be990c922e10e4c620d6367cab1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7582,7 +7582,7 @@
|
||||
"description": "Provides a structured process for converting a Request into a Response",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.4.6"
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.4.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7602,7 +7602,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-26T08:30:57+00:00"
|
||||
"time": "2026-03-06T16:33:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
@@ -7760,16 +7760,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v7.4.6",
|
||||
"version": "v7.4.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "9fc881d95feae4c6c48678cb6372bd8a7ba04f5f"
|
||||
"reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/9fc881d95feae4c6c48678cb6372bd8a7ba04f5f",
|
||||
"reference": "9fc881d95feae4c6c48678cb6372bd8a7ba04f5f",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/da5ab4fde3f6c88ab06e96185b9922f48b677cd1",
|
||||
"reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7825,7 +7825,7 @@
|
||||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v7.4.6"
|
||||
"source": "https://github.com/symfony/mime/tree/v7.4.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7845,7 +7845,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-05T15:57:06+00:00"
|
||||
"time": "2026-03-05T15:24:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
|
||||
@@ -36,12 +36,12 @@ use Illuminate\Support\Facades\URL;
|
||||
use Spatie\Html\Facades\Html;
|
||||
|
||||
return [
|
||||
'name' => envNonEmpty('APP_NAME', 'Firefly III'),
|
||||
'env' => envNonEmpty('APP_ENV', 'production'),
|
||||
'name' => envDefaultWhenEmpty(env('APP_NAME'), 'Firefly III'),
|
||||
'env' => envDefaultWhenEmpty(env('APP_ENV'), 'production'),
|
||||
'debug' => env('APP_DEBUG', false),
|
||||
'url' => envNonEmpty('APP_URL', 'http://localhost'),
|
||||
'timezone' => envNonEmpty('TZ', 'UTC'),
|
||||
'locale' => envNonEmpty('DEFAULT_LANGUAGE', 'en_US'),
|
||||
'url' => envDefaultWhenEmpty(env('APP_URL'), 'http://localhost'),
|
||||
'timezone' => envDefaultWhenEmpty(env('TZ'), 'UTC'),
|
||||
'locale' => envDefaultWhenEmpty(env('DEFAULT_LANGUAGE'), 'en_US'),
|
||||
'fallback_locale' => 'en_US',
|
||||
'key' => env('APP_KEY'),
|
||||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
@@ -37,11 +37,11 @@ return [
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
'guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'),
|
||||
'guard' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD'), 'web'),
|
||||
'passwords' => 'users',
|
||||
],
|
||||
'guard_header' => envNonEmpty('AUTHENTICATION_GUARD_HEADER', 'REMOTE_USER'),
|
||||
'guard_email' => envNonEmpty('AUTHENTICATION_GUARD_EMAIL'),
|
||||
'guard_header' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD_HEADER'), 'REMOTE_USER'),
|
||||
'guard_email' => env('AUTHENTICATION_GUARD_EMAIL'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -36,7 +36,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => envNonEmpty('CACHE_DRIVER', 'file'),
|
||||
'default' => envDefaultWhenEmpty(env('CACHE_DRIVER'), 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -41,15 +41,15 @@ if (false !== $databaseUrl) {
|
||||
}
|
||||
|
||||
// Get SSL parameters from .env file.
|
||||
$mysql_ssl_ca_dir = envNonEmpty('MYSQL_SSL_CAPATH');
|
||||
$mysql_ssl_ca_file = envNonEmpty('MYSQL_SSL_CA');
|
||||
$mysql_ssl_cert = envNonEmpty('MYSQL_SSL_CERT');
|
||||
$mysql_ssl_key = envNonEmpty('MYSQL_SSL_KEY');
|
||||
$mysql_ssl_ciphers = envNonEmpty('MYSQL_SSL_CIPHER');
|
||||
$mysql_ssl_verify = envNonEmpty('MYSQL_SSL_VERIFY_SERVER_CERT');
|
||||
$mysql_ssl_ca_dir = env('MYSQL_SSL_CAPATH');
|
||||
$mysql_ssl_ca_file = env('MYSQL_SSL_CA');
|
||||
$mysql_ssl_cert = env('MYSQL_SSL_CERT');
|
||||
$mysql_ssl_key = env('MYSQL_SSL_KEY');
|
||||
$mysql_ssl_ciphers = env('MYSQL_SSL_CIPHER');
|
||||
$mysql_ssl_verify = env('MYSQL_SSL_VERIFY_SERVER_CERT');
|
||||
|
||||
$mySqlSSLOptions = [];
|
||||
$useSSL = envNonEmpty('MYSQL_USE_SSL', false);
|
||||
$useSSL = envDefaultWhenEmpty(env('MYSQL_USE_SSL'), false);
|
||||
if (false !== $useSSL && null !== $useSSL && '' !== $useSSL) {
|
||||
if (null !== $mysql_ssl_ca_dir) {
|
||||
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CAPATH] = $mysql_ssl_ca_dir;
|
||||
@@ -72,19 +72,19 @@ if (false !== $useSSL && null !== $useSSL && '' !== $useSSL) {
|
||||
}
|
||||
|
||||
return [
|
||||
'default' => envNonEmpty('DB_CONNECTION', 'mysql'),
|
||||
'default' => envDefaultWhenEmpty(env('DB_CONNECTION'), 'mysql'),
|
||||
'connections' => [
|
||||
'sqlite' => [
|
||||
'driver' => 'sqlite',
|
||||
'database' => envNonEmpty('DB_DATABASE', storage_path('database/database.sqlite')),
|
||||
'database' => envDefaultWhenEmpty(env('DB_DATABASE'), storage_path('database/database.sqlite')),
|
||||
'prefix' => '',
|
||||
],
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'host' => envNonEmpty('DB_HOST', $host),
|
||||
'port' => envNonEmpty('DB_PORT', $port),
|
||||
'database' => envNonEmpty('DB_DATABASE', $database),
|
||||
'username' => envNonEmpty('DB_USERNAME', $username),
|
||||
'host' => envDefaultWhenEmpty(env('DB_HOST'), $host),
|
||||
'port' => envDefaultWhenEmpty(env('DB_PORT'), $port),
|
||||
'database' => envDefaultWhenEmpty(env('DB_DATABASE'), $database),
|
||||
'username' => envDefaultWhenEmpty(env('DB_USERNAME'), $username),
|
||||
'password' => env('DB_PASSWORD', $password),
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'charset' => 'utf8mb4',
|
||||
@@ -96,19 +96,19 @@ return [
|
||||
],
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'host' => envNonEmpty('DB_HOST', $host),
|
||||
'port' => envNonEmpty('DB_PORT', $port),
|
||||
'database' => envNonEmpty('DB_DATABASE', $database),
|
||||
'username' => envNonEmpty('DB_USERNAME', $username),
|
||||
'host' => envDefaultWhenEmpty(env('DB_HOST'), $host),
|
||||
'port' => envDefaultWhenEmpty(env('DB_PORT'), $port),
|
||||
'database' => envDefaultWhenEmpty(env('DB_DATABASE'), $database),
|
||||
'username' => envDefaultWhenEmpty(env('DB_USERNAME'), $username),
|
||||
'password' => env('DB_PASSWORD', $password),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'search_path' => envNonEmpty('PGSQL_SCHEMA', 'public'),
|
||||
'schema' => envNonEmpty('PGSQL_SCHEMA', 'public'),
|
||||
'sslmode' => envNonEmpty('PGSQL_SSL_MODE', 'prefer'),
|
||||
'sslcert' => envNonEmpty('PGSQL_SSL_CERT'),
|
||||
'sslkey' => envNonEmpty('PGSQL_SSL_KEY'),
|
||||
'sslrootcert' => envNonEmpty('PGSQL_SSL_ROOT_CERT'),
|
||||
'search_path' => envDefaultWhenEmpty(env('PGSQL_SCHEMA'), 'public'),
|
||||
'schema' => envDefaultWhenEmpty(env('PGSQL_SCHEMA'), 'public'),
|
||||
'sslmode' => envDefaultWhenEmpty(env('PGSQL_SSL_MODE'), 'prefer'),
|
||||
'sslcert' => env('PGSQL_SSL_CERT'),
|
||||
'sslkey' => env('PGSQL_SSL_KEY'),
|
||||
'sslrootcert' => env('PGSQL_SSL_ROOT_CERT'),
|
||||
],
|
||||
'sqlsrv' => [
|
||||
'driver' => 'sqlsrv',
|
||||
@@ -139,21 +139,21 @@ return [
|
||||
// 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'),
|
||||
],
|
||||
'default' => [
|
||||
'scheme' => envNonEmpty('REDIS_SCHEME', 'tcp'),
|
||||
'url' => envNonEmpty('REDIS_URL'),
|
||||
'path' => envNonEmpty('REDIS_PATH'),
|
||||
'host' => envNonEmpty('REDIS_HOST', '127.0.0.1'),
|
||||
'port' => envNonEmpty('REDIS_PORT', 6379),
|
||||
'scheme' => envDefaultWhenEmpty(env('REDIS_SCHEME'), 'tcp'),
|
||||
'url' => env('REDIS_URL'),
|
||||
'path' => env('REDIS_PATH'),
|
||||
'host' => envDefaultWhenEmpty(env('REDIS_HOST'), '127.0.0.1'),
|
||||
'port' => envDefaultWhenEmpty(env('REDIS_PORT'), 6379),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'database' => env('REDIS_DB', '0'),
|
||||
],
|
||||
'cache' => [
|
||||
'scheme' => envNonEmpty('REDIS_SCHEME', 'tcp'),
|
||||
'url' => envNonEmpty('REDIS_URL'),
|
||||
'path' => envNonEmpty('REDIS_PATH'),
|
||||
'host' => envNonEmpty('REDIS_HOST', '127.0.0.1'),
|
||||
'port' => envNonEmpty('REDIS_PORT', 6379),
|
||||
'scheme' => envDefaultWhenEmpty(env('REDIS_SCHEME'), 'tcp'),
|
||||
'url' => env('REDIS_URL'),
|
||||
'path' => env('REDIS_PATH'),
|
||||
'host' => envDefaultWhenEmpty(env('REDIS_HOST'), '127.0.0.1'),
|
||||
'port' => envDefaultWhenEmpty(env('REDIS_PORT'), 6379),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'database' => env('REDIS_CACHE_DB', '1'),
|
||||
|
||||
@@ -75,14 +75,20 @@ return [
|
||||
'webhooks' => true,
|
||||
'handle_debts' => true,
|
||||
'expression_engine' => true,
|
||||
'running_balance_column' => (bool)envNonEmpty('USE_RUNNING_BALANCE', true), // this is only the default value, is not used.
|
||||
'running_balance_column' => (bool)envDefaultWhenEmpty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used.
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => 'develop/2026-03-06',
|
||||
'build_time' => 1772780248,
|
||||
'build_time' => 1772825351,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 28, // field is no longer used.
|
||||
|
||||
// Docker build info, if present:
|
||||
'is_docker' => env('IS_DOCKER', false),
|
||||
'base_image_build' => envDefaultWhenEmpty(env('BASE_IMAGE_BUILD'), '(unknown)'),
|
||||
'base_image_date' => envDefaultWhenEmpty(env('BASE_IMAGE_DATE'), '(unknown)'),
|
||||
'is_local_dev' => env('IS_LOCAL_DEV', false),
|
||||
|
||||
// generic settings
|
||||
'maxUploadSize' => 1073741824, // 1 GB
|
||||
'send_error_message' => env('SEND_ERROR_MESSAGE', true),
|
||||
@@ -91,7 +97,7 @@ return [
|
||||
// tokens and keys
|
||||
'fixer_api_key' => env('FIXER_API_KEY', ''),
|
||||
'ipinfo_token' => env('IPINFO_TOKEN', ''),
|
||||
'static_cron_token' => envNonEmpty('STATIC_CRON_TOKEN'),
|
||||
'static_cron_token' => env('STATIC_CRON_TOKEN'),
|
||||
|
||||
// flags
|
||||
'enable_external_map' => env('ENABLE_EXTERNAL_MAP', false), // no longer used, only for default.
|
||||
@@ -106,8 +112,8 @@ return [
|
||||
'tracker_url' => env('TRACKER_URL', ''),
|
||||
|
||||
// authentication settings
|
||||
'authentication_guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'),
|
||||
'custom_logout_url' => envNonEmpty('CUSTOM_LOGOUT_URL', ''),
|
||||
'authentication_guard' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD'), 'web'),
|
||||
'custom_logout_url' => envDefaultWhenEmpty(env('CUSTOM_LOGOUT_URL'), ''),
|
||||
|
||||
// static config (cannot be changed by user)
|
||||
'update_endpoint' => 'https://version.firefly-iii.org/index.json',
|
||||
@@ -188,8 +194,8 @@ return [
|
||||
'convertToPrimary' => false,
|
||||
],
|
||||
'default_currency' => 'EUR',
|
||||
'default_language' => envNonEmpty('DEFAULT_LANGUAGE', 'en_US'),
|
||||
'default_locale' => envNonEmpty('DEFAULT_LOCALE', 'equal'),
|
||||
'default_language' => envDefaultWhenEmpty(env('DEFAULT_LANGUAGE'), 'en_US'),
|
||||
'default_locale' => envDefaultWhenEmpty(env('DEFAULT_LOCALE'), 'equal'),
|
||||
|
||||
// account types that may have or set a currency
|
||||
'valid_currency_account_types' => [
|
||||
@@ -218,7 +224,7 @@ return [
|
||||
'available_dark_modes' => ['light', 'dark', 'browser'],
|
||||
'bill_reminder_periods' => [90, 30, 14, 7, 0],
|
||||
'valid_view_ranges' => ['1D', '1W', '1M', '3M', '6M', '1Y'],
|
||||
'valid_url_protocols' => envNonEmpty('VALID_URL_PROTOCOLS', 'http,https,ftp,ftps,mailto'), // no longer used, only for default.
|
||||
'valid_url_protocols' => envDefaultWhenEmpty(env('VALID_URL_PROTOCOLS'), 'http,https,ftp,ftps,mailto'), // no longer used, only for default.
|
||||
'allowedMimes' => [
|
||||
// plain files
|
||||
'text/plain',
|
||||
|
||||
@@ -34,8 +34,8 @@ $validChannels = ['single', 'papertrail', 'stdout', 'daily', 'syslog', 'err
|
||||
$validAuditChannels = ['audit_papertrail', 'audit_stdout', 'audit_stdout', 'audit_daily', 'audit_syslog', 'audit_errorlog'];
|
||||
|
||||
// which settings did the user set, if any?
|
||||
$defaultLogChannel = (string) envNonEmpty('LOG_CHANNEL', 'stack');
|
||||
$auditLogChannel = (string) envNonEmpty('AUDIT_LOG_CHANNEL', '');
|
||||
$defaultLogChannel = (string) envDefaultWhenEmpty(env('LOG_CHANNEL'), 'stack');
|
||||
$auditLogChannel = (string) env('AUDIT_LOG_CHANNEL');
|
||||
|
||||
if ('stack' === $defaultLogChannel) {
|
||||
$defaultChannels = ['daily', 'stdout'];
|
||||
@@ -60,8 +60,8 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => envNonEmpty('LOG_CHANNEL', 'stack'),
|
||||
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
|
||||
'default' => envDefaultWhenEmpty(env('LOG_CHANNEL'), 'stack'),
|
||||
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Channels
|
||||
@@ -93,11 +93,11 @@ return [
|
||||
'single' => [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
|
||||
],
|
||||
'papertrail' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
|
||||
'handler' => SyslogUdpHandler::class,
|
||||
'handler_with' => [
|
||||
'host' => env('PAPERTRAIL_HOST'),
|
||||
@@ -107,21 +107,21 @@ return [
|
||||
'stdout' => [
|
||||
'driver' => 'single',
|
||||
'path' => 'php://stdout',
|
||||
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
|
||||
],
|
||||
'daily' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/ff3-'.PHP_SAPI.'.log'),
|
||||
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
|
||||
'days' => 7,
|
||||
],
|
||||
'syslog' => [
|
||||
'driver' => 'syslog',
|
||||
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
|
||||
],
|
||||
'errorlog' => [
|
||||
'driver' => 'errorlog',
|
||||
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -130,7 +130,7 @@ return [
|
||||
*/
|
||||
'audit_papertrail' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
|
||||
'handler' => SyslogUdpHandler::class,
|
||||
'tap' => [AuditLogger::class],
|
||||
'handler_with' => [
|
||||
@@ -142,24 +142,24 @@ return [
|
||||
'driver' => 'single',
|
||||
'path' => 'php://stdout',
|
||||
'tap' => [AuditLogger::class],
|
||||
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
|
||||
],
|
||||
'audit_daily' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/ff3-audit.log'),
|
||||
'tap' => [AuditLogger::class],
|
||||
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
|
||||
'days' => 90,
|
||||
],
|
||||
'audit_syslog' => [
|
||||
'driver' => 'syslog',
|
||||
'tap' => [AuditLogger::class],
|
||||
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
|
||||
],
|
||||
'audit_errorlog' => [
|
||||
'driver' => 'errorlog',
|
||||
'tap' => [AuditLogger::class],
|
||||
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
|
||||
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -34,16 +34,16 @@ return [
|
||||
| and used as needed; however, this mailer will be used by default.
|
||||
|
|
||||
*/
|
||||
'default' => envNonEmpty('MAIL_MAILER', 'log'),
|
||||
'default' => envDefaultWhenEmpty(env('MAIL_MAILER'), 'log'),
|
||||
|
||||
'mailers' => [
|
||||
'smtp' => [
|
||||
'transport' => 'smtp',
|
||||
'host' => envNonEmpty('MAIL_HOST', 'smtp.mailtrap.io'),
|
||||
'host' => envDefaultWhenEmpty(env('MAIL_HOST'), 'smtp.mailtrap.io'),
|
||||
'port' => (int) env('MAIL_PORT', 2525),
|
||||
'encryption' => envNonEmpty('MAIL_ENCRYPTION', 'tls'),
|
||||
'username' => envNonEmpty('MAIL_USERNAME', 'user@example.com'),
|
||||
'password' => envNonEmpty('MAIL_PASSWORD', 'password'),
|
||||
'encryption' => envDefaultWhenEmpty(env('MAIL_ENCRYPTION'), 'tls'),
|
||||
'username' => envDefaultWhenEmpty(env('MAIL_USERNAME'), 'user@example.com'),
|
||||
'password' => envDefaultWhenEmpty(env('MAIL_PASSWORD'), 'password'),
|
||||
'timeout' => null,
|
||||
'scheme' => env('MAIL_SCHEME'),
|
||||
'url' => env('MAIL_URL'),
|
||||
@@ -73,7 +73,7 @@ return [
|
||||
|
||||
'sendmail' => [
|
||||
'transport' => 'sendmail',
|
||||
'path' => envNonEmpty('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs'),
|
||||
'path' => envDefaultWhenEmpty(env('MAIL_SENDMAIL_COMMAND'), '/usr/sbin/sendmail -bs'),
|
||||
],
|
||||
'log' => [
|
||||
'transport' => 'log',
|
||||
@@ -91,7 +91,7 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
'from' => ['address' => envNonEmpty('MAIL_FROM', 'changeme@example.com'), 'name' => 'Firefly III Mailer'],
|
||||
'from' => ['address' => envDefaultWhenEmpty(env('MAIL_FROM'), 'changeme@example.com'), 'name' => 'Firefly III Mailer'],
|
||||
'markdown' => [
|
||||
'theme' => 'default',
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'),
|
||||
'guard' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD'), 'web'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -29,7 +29,7 @@ use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration {
|
||||
protected static function hasForeign(string $table, string $column): bool
|
||||
private static function hasForeign(string $table, string $column): bool
|
||||
{
|
||||
$foreignKeysDefinitions = Schema::getForeignKeys($table);
|
||||
foreach ($foreignKeysDefinitions as $foreignKeyDefinition) {
|
||||
|
||||
30
package-lock.json
generated
30
package-lock.json
generated
@@ -200,9 +200,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-define-polyfill-provider": {
|
||||
"version": "0.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz",
|
||||
"integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==",
|
||||
"version": "0.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.7.tgz",
|
||||
"integrity": "sha512-6Fqi8MtQ/PweQ9xvux65emkLQ83uB+qAVtfHkC9UodyHMIZdxNI01HjLCLUtybElp2KY2XNE0nOgyP1E1vXw9w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1586,13 +1586,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.0.tgz",
|
||||
"integrity": "sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==",
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.1.tgz",
|
||||
"integrity": "sha512-ENp89vM9Pw4kv/koBb5N2f9bDZsR0hpf3BdPMOg/pkS3pwO4dzNnQZVXtBbeyAadgm865DmQG2jMMLqmZXvuCw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.6",
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.7",
|
||||
"core-js-compat": "^3.48.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -4055,14 +4055,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-polyfill-corejs2": {
|
||||
"version": "0.4.15",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz",
|
||||
"integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==",
|
||||
"version": "0.4.16",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.16.tgz",
|
||||
"integrity": "sha512-xaVwwSfebXf0ooE11BJovZYKhFjIvQo7TsyVpETuIeH2JHv0k/T6Y5j22pPTvqYqmpkxdlPAJlyJ0tfOJAoMxw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.28.6",
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.6",
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.7",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -4094,13 +4094,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-polyfill-regenerator": {
|
||||
"version": "0.6.6",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz",
|
||||
"integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==",
|
||||
"version": "0.6.7",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.7.tgz",
|
||||
"integrity": "sha512-OTYbUlSwXhNgr4g6efMZgsO8//jA61P7ZbRX3iTT53VON8l+WQS8IAUEVo4a4cWknrg2W8Cj4gQhRYNCJ8GkAA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.6"
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||
|
||||
Reference in New Issue
Block a user