Compare commits

..

13 Commits

Author SHA1 Message Date
github-actions[bot] 33ad34a719 Merge pull request #12183 from firefly-iii/release-1777088715
🤖 Automatically merge the PR into the develop branch.
2026-04-25 05:45:23 +02:00
JC5 dca1d962af 🤖 Auto commit for release 'develop' on 2026-04-25 2026-04-25 05:45:16 +02:00
James Cole 0e97b4a6b8 Add script and add exception. 2026-04-24 10:26:48 +02:00
github-actions[bot] 3de7cfd3bf Merge pull request #12181 from firefly-iii/release-1777003029
🤖 Automatically merge the PR into the develop branch.
2026-04-24 05:57:17 +02:00
JC5 a6fd805202 🤖 Auto commit for release 'develop' on 2026-04-24 2026-04-24 05:57:09 +02:00
James Cole 541e1ac7b4 And now fix them for real. 2026-04-24 05:51:44 +02:00
James Cole 1c6b8af3a3 Fix Mago issues. 2026-04-24 05:45:42 +02:00
James Cole b33b22e0b3 Let's add some authentication before I am drowned in reports. 2026-04-24 05:37:55 +02:00
James Cole 30cce327e8 Add helpers and fix missing string. 2026-04-24 05:34:40 +02:00
James Cole 994e3dae18 Merge pull request #12179 from tasnim0tantawi/feature/client-side-password-verification-on-register
implement password validation JS script
2026-04-24 05:09:19 +02:00
tasnim0tantawi b065150968 implement password validation JS script 2026-04-23 22:08:24 +03:00
James Cole d18e9ffad0 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2026-04-23 03:08:53 +02:00
James Cole fad5438909 Fix https://github.com/firefly-iii/firefly-iii/issues/12170 2026-04-23 03:07:03 +02:00
26 changed files with 355 additions and 169 deletions
+1
View File
@@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2026
- tasnim0tantawi
- Joe Longendyke
- Daniel Holøien
- Matthew Grove
+105
View File
@@ -0,0 +1,105 @@
<?php
/*
* helpers.php
* Copyright (c) 2026 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
use FireflyIII\Exceptions\FireflyException;
use function Safe\mb_ord;
use function Safe\preg_match;
use function Safe\preg_replace_callback;
if (!function_exists('env_default_when_empty')) {
/**
* @return null|mixed
*/
function env_default_when_empty(mixed $value, bool|int|string|null $default = null): mixed
{
if (null === $value) {
return $default;
}
if ('' === $value) {
return $default;
}
return $value;
}
}
if (!function_exists('string_is_equal')) {
function string_is_equal(string $left, string $right): bool
{
return $left === $right;
}
}
if (!function_exists('blade_escape_js')) {
function blade_escape_js(string $string): string
{
// escape all non-alphanumeric characters
// into their \x or \uHHHH representations
if (0 === preg_match('//u', $string)) {
throw new FireflyException('The string to escape is not a valid UTF-8 string.');
}
return preg_replace_callback(
'#[^a-zA-Z0-9,\._]#Su',
static function ($matches) {
$char = $matches[0];
/*
* A few characters have short escape sequences in JSON and JavaScript.
* Escape sequences supported only by JavaScript, not JSON, are omitted.
* \" is also supported but omitted, because the resulting string is not HTML safe.
*/
$short = match ($char) {
'\\' => '\\\\',
'/' => '\/',
"\x08" => '\b',
"\x0C" => '\f',
"\x0A" => '\n',
"\x0D" => '\r',
"\x09" => '\t',
default => false
};
if ($short) {
return $short;
}
$codepoint = mb_ord($char, 'UTF-8');
if (0x10_000 > $codepoint) {
return \sprintf('\u%04X', $codepoint);
}
// Split characters outside the BMP into surrogate pairs
// https://tools.ietf.org/html/rfc2781.html#section-2.1
$u = $codepoint - 0x10_000;
$high = 0xD800 | ($u >> 10);
$low = 0xDC00 | ($u & 0x3FF);
return \sprintf('\u%04X\u%04X', $high, $low);
},
$string
);
}
}
@@ -115,6 +115,9 @@ final class OAuthController extends Controller
public function listClients(): JsonResponse
{
if (!auth()->check()) {
return response()->json([]);
}
Log::debug('Now in listClients()');
// Retrieving all the OAuth app clients that belong to the user...
$clients = auth()->user()->oauthApps()->where('revoked', false)->get();
+1 -1
View File
@@ -63,7 +63,7 @@ class SecureHeaders
"base-uri 'self'",
// "form-action 'self'", // safe
"font-src 'self' data:",
sprintf("connect-src 'self' %s", $trackingScriptSrc),
sprintf("connect-src 'self' https://api.pwnedpasswords.com %s", $trackingScriptSrc),
sprintf("img-src 'self' data: 'nonce-%1s' ", $nonce),
"manifest-src 'self'",
];
@@ -98,7 +98,7 @@ trait ModifiesPiggyBanks
$maxAmount = $leftOnAccount;
Log::debug(sprintf('Left on account: %s on %s', $leftOnAccount, $today->format('Y-m-d H:i:s')));
Log::debug(sprintf('Saved so far: %s', $savedSoFar));
Log::debug(sprintf('Saved so far : %s', $savedSoFar));
if (0 !== bccomp($piggyBank->target_amount, '0')) {
$leftToSave = bcsub($piggyBank->target_amount, (string) $savedSoFar);
@@ -110,7 +110,7 @@ trait ModifiesPiggyBanks
$compare = bccomp($amount, (string) $maxAmount);
$result = $compare <= 0;
Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true)));
Log::debug(sprintf('Compare %s to %s <= 0? %d, so canAddAmount is %s', $amount, $maxAmount, $compare, var_export($result, true)));
return $result;
}
+5 -4
View File
@@ -54,8 +54,9 @@ class IsEnoughInAccounts implements ValidationRule
$accounts = $this->data['accounts'];
foreach ($accounts as $info) {
$account = $repository->find((int) $info['account_id']);
$amount = $info['current_amount'] ?? '0';
$account = $repository->find((int) $info['account_id']);
$amount = $info['current_amount'] ?? '0';
$savedSoFar = $piggyRepos->getCurrentAmount($this->piggyBank, $account);
if (null === $account) {
$fail('validation.no_asset_account')->translate();
@@ -64,8 +65,8 @@ class IsEnoughInAccounts implements ValidationRule
if ('' === $amount || 0 === bccomp($amount, '0')) {
continue;
}
$diff = bcsub($amount, $piggyRepos->getCurrentAmount($this->piggyBank, $account));
if (1 === bccomp($diff, '0') && !$piggyRepos->canAddAmount($this->piggyBank, $account, $amount)) {
$diff = bcsub($amount, $savedSoFar);
if (1 === bccomp($diff, '0') && !$piggyRepos->canAddAmount($this->piggyBank, $account, $diff)) {
$fail('validation.cannot_add_piggy_amount')->translate();
}
}
+2 -2
View File
@@ -522,7 +522,7 @@ class OperatorQuerySearch implements SearchInterface
$stringMethod = 'str_contains';
}
if (StringPosition::IS === $stringPosition) {
$stringMethod = 'stringIsEqual';
$stringMethod = 'string_is_equal';
}
// get accounts:
@@ -619,7 +619,7 @@ class OperatorQuerySearch implements SearchInterface
$stringMethod = 'str_contains';
}
if (StringPosition::IS === $stringPosition) {
$stringMethod = 'stringIsEqual';
$stringMethod = 'string_is_equal';
}
// search for accounts:
-22
View File
@@ -63,29 +63,7 @@ use PragmaRX\Google2FALaravel\Middleware as MFAMiddleware;
bcscale(12);
if (!function_exists('envDefaultWhenEmpty')) {
/**
*
* @return mixed|null
*/
function envDefaultWhenEmpty(mixed $value, string | int | bool | null $default = null): mixed
{
if(null === $value) {
return $default;
}
if('' === $value) {
return $default;
}
return $value;
}
}
if (!function_exists('stringIsEqual')) {
function stringIsEqual(string $left, string $right): bool
{
return $left === $right;
}
}
$app = Application::configure(basePath: dirname(__DIR__))
->withRouting(
+3
View File
@@ -135,6 +135,9 @@
"suggest": {},
"autoload": {
"files": [
"app/Helpers/Functions/helpers.php"
],
"psr-4": {
"FireflyIII\\": "app/",
"Domain\\": "domain/",
Generated
+7 -6
View File
@@ -11511,21 +11511,22 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "14.1.3",
"version": "14.1.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "24dc6fcf9f2a983de5b3f1199fb01e88d68e7474"
"reference": "4991e47adce8e31e554aee8fdaabfc3b1d60707d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/24dc6fcf9f2a983de5b3f1199fb01e88d68e7474",
"reference": "24dc6fcf9f2a983de5b3f1199fb01e88d68e7474",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4991e47adce8e31e554aee8fdaabfc3b1d60707d",
"reference": "4991e47adce8e31e554aee8fdaabfc3b1d60707d",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^5.7.0",
"php": ">=8.4",
@@ -11576,7 +11577,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/14.1.3"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/14.1.6"
},
"funding": [
{
@@ -11596,7 +11597,7 @@
"type": "tidelift"
}
],
"time": "2026-04-18T05:41:54+00:00"
"time": "2026-04-24T13:10:08+00:00"
},
{
"name": "phpunit/php-file-iterator",
+5 -5
View File
@@ -36,12 +36,12 @@ use Illuminate\Support\Facades\URL;
use Spatie\Html\Facades\Html;
return [
'name' => envDefaultWhenEmpty(env('APP_NAME'), 'Firefly III'),
'env' => envDefaultWhenEmpty(env('APP_ENV'), 'production'),
'name' => env_default_when_empty(env('APP_NAME'), 'Firefly III'),
'env' => env_default_when_empty(env('APP_ENV'), 'production'),
'debug' => env('APP_DEBUG', false),
'url' => envDefaultWhenEmpty(env('APP_URL'), 'http://localhost'),
'timezone' => envDefaultWhenEmpty(env('TZ'), 'UTC'),
'locale' => envDefaultWhenEmpty(env('DEFAULT_LANGUAGE'), 'en_US'),
'url' => env_default_when_empty(env('APP_URL'), 'http://localhost'),
'timezone' => env_default_when_empty(env('TZ'), 'UTC'),
'locale' => env_default_when_empty(env('DEFAULT_LANGUAGE'), 'en_US'),
'fallback_locale' => 'en_US',
'key' => env('APP_KEY'),
'cipher' => 'AES-256-CBC',
+2 -2
View File
@@ -37,10 +37,10 @@ return [
*/
'defaults' => [
'guard' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD'), 'web'),
'guard' => env_default_when_empty(env('AUTHENTICATION_GUARD'), 'web'),
'passwords' => 'users',
],
'guard_header' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD_HEADER'), 'REMOTE_USER'),
'guard_header' => env_default_when_empty(env('AUTHENTICATION_GUARD_HEADER'), 'REMOTE_USER'),
'guard_email' => env('AUTHENTICATION_GUARD_EMAIL'),
/*
+1 -1
View File
@@ -36,7 +36,7 @@ return [
|
*/
'default' => envDefaultWhenEmpty(env('CACHE_DRIVER'), 'file'),
'default' => env_default_when_empty(env('CACHE_DRIVER'), 'file'),
/*
|--------------------------------------------------------------------------
+20 -20
View File
@@ -49,7 +49,7 @@ $mysql_ssl_ciphers = env('MYSQL_SSL_CIPHER');
$mysql_ssl_verify = env('MYSQL_SSL_VERIFY_SERVER_CERT');
$mySqlSSLOptions = [];
$useSSL = envDefaultWhenEmpty(env('MYSQL_USE_SSL'), false);
$useSSL = env_default_when_empty(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' => envDefaultWhenEmpty(env('DB_CONNECTION'), 'mysql'),
'default' => env_default_when_empty(env('DB_CONNECTION'), 'mysql'),
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => envDefaultWhenEmpty(env('DB_DATABASE'), storage_path('database/database.sqlite')),
'database' => env_default_when_empty(env('DB_DATABASE'), storage_path('database/database.sqlite')),
'prefix' => '',
],
'mysql' => [
'driver' => 'mysql',
'host' => envDefaultWhenEmpty(env('DB_HOST'), $host),
'port' => envDefaultWhenEmpty(env('DB_PORT'), $port),
'database' => envDefaultWhenEmpty(env('DB_DATABASE'), $database),
'username' => envDefaultWhenEmpty(env('DB_USERNAME'), $username),
'host' => env_default_when_empty(env('DB_HOST'), $host),
'port' => env_default_when_empty(env('DB_PORT'), $port),
'database' => env_default_when_empty(env('DB_DATABASE'), $database),
'username' => env_default_when_empty(env('DB_USERNAME'), $username),
'password' => env('DB_PASSWORD', $password),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
@@ -96,16 +96,16 @@ return [
],
'pgsql' => [
'driver' => 'pgsql',
'host' => envDefaultWhenEmpty(env('DB_HOST'), $host),
'port' => envDefaultWhenEmpty(env('DB_PORT'), $port),
'database' => envDefaultWhenEmpty(env('DB_DATABASE'), $database),
'username' => envDefaultWhenEmpty(env('DB_USERNAME'), $username),
'host' => env_default_when_empty(env('DB_HOST'), $host),
'port' => env_default_when_empty(env('DB_PORT'), $port),
'database' => env_default_when_empty(env('DB_DATABASE'), $database),
'username' => env_default_when_empty(env('DB_USERNAME'), $username),
'password' => env('DB_PASSWORD', $password),
'charset' => 'utf8',
'prefix' => '',
'search_path' => envDefaultWhenEmpty(env('PGSQL_SCHEMA'), 'public'),
'schema' => envDefaultWhenEmpty(env('PGSQL_SCHEMA'), 'public'),
'sslmode' => envDefaultWhenEmpty(env('PGSQL_SSL_MODE'), 'prefer'),
'search_path' => env_default_when_empty(env('PGSQL_SCHEMA'), 'public'),
'schema' => env_default_when_empty(env('PGSQL_SCHEMA'), 'public'),
'sslmode' => env_default_when_empty(env('PGSQL_SSL_MODE'), 'prefer'),
'sslcert' => env('PGSQL_SSL_CERT'),
'sslkey' => env('PGSQL_SSL_KEY'),
'sslrootcert' => env('PGSQL_SSL_ROOT_CERT'),
@@ -139,21 +139,21 @@ return [
// 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'),
],
'default' => [
'scheme' => envDefaultWhenEmpty(env('REDIS_SCHEME'), 'tcp'),
'scheme' => env_default_when_empty(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),
'host' => env_default_when_empty(env('REDIS_HOST'), '127.0.0.1'),
'port' => env_default_when_empty(env('REDIS_PORT'), 6379),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'database' => env('REDIS_DB', '0'),
],
'cache' => [
'scheme' => envDefaultWhenEmpty(env('REDIS_SCHEME'), 'tcp'),
'scheme' => env_default_when_empty(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),
'host' => env_default_when_empty(env('REDIS_HOST'), '127.0.0.1'),
'port' => env_default_when_empty(env('REDIS_PORT'), 6379),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'database' => env('REDIS_CACHE_DB', '1'),
+10 -10
View File
@@ -75,18 +75,18 @@ return [
'webhooks' => true,
'handle_debts' => true,
'expression_engine' => true,
'running_balance_column' => (bool)envDefaultWhenEmpty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used.
'running_balance_column' => (bool)env_default_when_empty(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-04-22',
'build_time' => 1776876664,
'version' => 'develop/2026-04-25',
'build_time' => 1777088715,
'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)'),
'base_image_build' => env_default_when_empty(env('BASE_IMAGE_BUILD'), '(unknown)'),
'base_image_date' => env_default_when_empty(env('BASE_IMAGE_DATE'), '(unknown)'),
'is_local_dev' => env('IS_LOCAL_DEV', false),
// generic settings
@@ -112,8 +112,8 @@ return [
'tracker_url' => env('TRACKER_URL', ''),
// authentication settings
'authentication_guard' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD'), 'web'),
'custom_logout_url' => envDefaultWhenEmpty(env('CUSTOM_LOGOUT_URL'), ''),
'authentication_guard' => env_default_when_empty(env('AUTHENTICATION_GUARD'), 'web'),
'custom_logout_url' => env_default_when_empty(env('CUSTOM_LOGOUT_URL'), ''),
// static config (cannot be changed by user)
'update_endpoint' => 'https://version.firefly-iii.org/index.json',
@@ -194,8 +194,8 @@ return [
'convertToPrimary' => false,
],
'default_currency' => 'EUR',
'default_language' => envDefaultWhenEmpty(env('DEFAULT_LANGUAGE'), 'en_US'),
'default_locale' => envDefaultWhenEmpty(env('DEFAULT_LOCALE'), 'equal'),
'default_language' => env_default_when_empty(env('DEFAULT_LANGUAGE'), 'en_US'),
'default_locale' => env_default_when_empty(env('DEFAULT_LOCALE'), 'equal'),
// account types that may have or set a currency
'valid_currency_account_types' => [
@@ -224,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' => envDefaultWhenEmpty(env('VALID_URL_PROTOCOLS'), 'http,https,ftp,ftps,mailto'), // no longer used, only for default.
'valid_url_protocols' => env_default_when_empty(env('VALID_URL_PROTOCOLS'), 'http,https,ftp,ftps,mailto'), // no longer used, only for default.
'allowedMimes' => [
// plain files
'text/plain',
+14 -14
View File
@@ -34,7 +34,7 @@ $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) envDefaultWhenEmpty(env('LOG_CHANNEL'), 'stack');
$defaultLogChannel = (string) env_default_when_empty(env('LOG_CHANNEL'), 'stack');
$auditLogChannel = (string) env('AUDIT_LOG_CHANNEL');
if ('stack' === $defaultLogChannel) {
@@ -60,8 +60,8 @@ return [
|
*/
'default' => envDefaultWhenEmpty(env('LOG_CHANNEL'), 'stack'),
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
'default' => env_default_when_empty(env('LOG_CHANNEL'), 'stack'),
'level' => env_default_when_empty(env('APP_LOG_LEVEL'), 'info'),
/*
|--------------------------------------------------------------------------
| Log Channels
@@ -93,11 +93,11 @@ return [
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('APP_LOG_LEVEL'), 'info'),
],
'papertrail' => [
'driver' => 'monolog',
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(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' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('APP_LOG_LEVEL'), 'info'),
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/ff3-'.PHP_SAPI.'.log'),
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('APP_LOG_LEVEL'), 'info'),
'days' => 7,
],
'syslog' => [
'driver' => 'syslog',
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('APP_LOG_LEVEL'), 'info'),
],
'errorlog' => [
'driver' => 'errorlog',
'level' => envDefaultWhenEmpty(env('APP_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('APP_LOG_LEVEL'), 'info'),
],
/*
@@ -130,7 +130,7 @@ return [
*/
'audit_papertrail' => [
'driver' => 'monolog',
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(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' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('AUDIT_LOG_LEVEL'), 'info'),
],
'audit_daily' => [
'driver' => 'daily',
'path' => storage_path('logs/ff3-audit.log'),
'tap' => [AuditLogger::class],
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('AUDIT_LOG_LEVEL'), 'info'),
'days' => 90,
],
'audit_syslog' => [
'driver' => 'syslog',
'tap' => [AuditLogger::class],
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('AUDIT_LOG_LEVEL'), 'info'),
],
'audit_errorlog' => [
'driver' => 'errorlog',
'tap' => [AuditLogger::class],
'level' => envDefaultWhenEmpty(env('AUDIT_LOG_LEVEL'), 'info'),
'level' => env_default_when_empty(env('AUDIT_LOG_LEVEL'), 'info'),
],
],
];
+7 -7
View File
@@ -34,16 +34,16 @@ return [
| and used as needed; however, this mailer will be used by default.
|
*/
'default' => envDefaultWhenEmpty(env('MAIL_MAILER'), 'log'),
'default' => env_default_when_empty(env('MAIL_MAILER'), 'log'),
'mailers' => [
'smtp' => [
'transport' => 'smtp',
'host' => envDefaultWhenEmpty(env('MAIL_HOST'), 'smtp.mailtrap.io'),
'host' => env_default_when_empty(env('MAIL_HOST'), 'smtp.mailtrap.io'),
'port' => (int) env('MAIL_PORT', 2525),
'encryption' => envDefaultWhenEmpty(env('MAIL_ENCRYPTION'), 'tls'),
'username' => envDefaultWhenEmpty(env('MAIL_USERNAME'), 'user@example.com'),
'password' => envDefaultWhenEmpty(env('MAIL_PASSWORD'), 'password'),
'encryption' => env_default_when_empty(env('MAIL_ENCRYPTION'), 'tls'),
'username' => env_default_when_empty(env('MAIL_USERNAME'), 'user@example.com'),
'password' => env_default_when_empty(env('MAIL_PASSWORD'), 'password'),
'timeout' => null,
'scheme' => env('MAIL_SCHEME'),
'url' => env('MAIL_URL'),
@@ -73,7 +73,7 @@ return [
'sendmail' => [
'transport' => 'sendmail',
'path' => envDefaultWhenEmpty(env('MAIL_SENDMAIL_COMMAND'), '/usr/sbin/sendmail -bs'),
'path' => env_default_when_empty(env('MAIL_SENDMAIL_COMMAND'), '/usr/sbin/sendmail -bs'),
],
'log' => [
'transport' => 'log',
@@ -91,7 +91,7 @@ return [
],
],
'from' => ['address' => envDefaultWhenEmpty(env('MAIL_FROM'), 'changeme@example.com'), 'name' => 'Firefly III Mailer'],
'from' => ['address' => env_default_when_empty(env('MAIL_FROM'), 'changeme@example.com'), 'name' => 'Firefly III Mailer'],
'markdown' => [
'theme' => 'default',
+1 -1
View File
@@ -15,7 +15,7 @@ return [
|
*/
'guard' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD'), 'web'),
'guard' => env_default_when_empty(env('AUTHENTICATION_GUARD'), 'web'),
/*
|--------------------------------------------------------------------------
+47 -66
View File
@@ -3315,9 +3315,9 @@
"license": "MIT"
},
"node_modules/ajv": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
"integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3350,9 +3350,9 @@
}
},
"node_modules/ajv-formats/node_modules/ajv": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3738,9 +3738,9 @@
"license": "MIT"
},
"node_modules/body-parser": {
"version": "1.20.4",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
"integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
"version": "1.20.5",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
"integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3752,7 +3752,7 @@
"http-errors": "~2.0.1",
"iconv-lite": "~0.4.24",
"on-finished": "~2.4.1",
"qs": "~6.14.0",
"qs": "~6.15.1",
"raw-body": "~2.5.3",
"type-is": "~1.6.18",
"unpipe": "~1.0.0"
@@ -3779,22 +3779,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/body-parser/node_modules/qs": {
"version": "6.14.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
"integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/bonjour-service": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz",
@@ -5337,9 +5321,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.343",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.343.tgz",
"integrity": "sha512-YHnQ3MXI08icvL9ZKnEBy05F2EQ8ob01UaMOuMbM8l+4UcAq6MPPbBTJBbsBUg3H8JeZNt+O4fjsoWth3p6IFg==",
"version": "1.5.344",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz",
"integrity": "sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==",
"dev": true,
"license": "ISC"
},
@@ -5394,14 +5378,14 @@
}
},
"node_modules/enhanced-resolve": {
"version": "5.20.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz",
"integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==",
"version": "5.21.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
"integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
"dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.3.0"
"tapable": "^2.3.3"
},
"engines": {
"node": ">=10.13.0"
@@ -6646,9 +6630,9 @@
}
},
"node_modules/i18next": {
"version": "26.0.6",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.6.tgz",
"integrity": "sha512-A4U6eCXodIbrhf8EarRurB9/4ebyaurH4+fu4gig9bqxmpSt+fCAFm/GpRQDcN1Xzu/LdFCx4nYHsnM1edIIbg==",
"version": "26.0.8",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.8.tgz",
"integrity": "sha512-BRzLom0mhDhV9v0QhgUUHWQJuwFmnr1194xEcNLYD6ym8y8s542n4jXUvRLnhNTbh9PmpU6kGZamyuGHQMsGjw==",
"funding": [
{
"type": "individual",
@@ -6664,9 +6648,6 @@
}
],
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.29.2"
},
"peerDependencies": {
"typescript": "^5 || ^6"
},
@@ -6686,9 +6667,9 @@
}
},
"node_modules/i18next-http-backend": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.5.tgz",
"integrity": "sha512-QaWHnsxieEDcqKe+vo/RFqpiIFRi/KBqlOSPcUlvinBaISCeiTRCbtrazHAjtHtsLC66oDsROAH8frWkQzfMMQ==",
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.6.tgz",
"integrity": "sha512-mBOqy8993jtqAoj6XaI1XeC/8/9v6EPS+681ziegrPvTB0DoaCY7PpTS0SpY56qLMoS4OI1TZEM2Zf59zNh05w==",
"license": "MIT",
"dependencies": {
"cross-fetch": "4.1.0"
@@ -7712,9 +7693,9 @@
"license": "MIT"
},
"node_modules/loader-runner": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz",
"integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==",
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz",
"integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==",
"dev": true,
"license": "MIT",
"engines": {
@@ -10762,9 +10743,9 @@
}
},
"node_modules/terser": {
"version": "5.46.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.46.1.tgz",
"integrity": "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==",
"version": "5.46.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.46.2.tgz",
"integrity": "sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -10781,9 +10762,9 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz",
"integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==",
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.5.0.tgz",
"integrity": "sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10815,9 +10796,9 @@
}
},
"node_modules/terser-webpack-plugin/node_modules/ajv": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11689,9 +11670,9 @@
}
},
"node_modules/webpack-dev-middleware/node_modules/ajv": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11806,9 +11787,9 @@
}
},
"node_modules/webpack-dev-server/node_modules/ajv": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11926,9 +11907,9 @@
}
},
"node_modules/webpack/node_modules/ajv": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11983,9 +11964,9 @@
}
},
"node_modules/webpack/node_modules/webpack-sources": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz",
"integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==",
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.0.tgz",
"integrity": "sha512-gHwIe1cgBvvfLeu1Yz/dcFpmHfKDVxxyqI+kzqmuxZED81z2ChxpyqPaWcNqigPywhaEke7AjSGga+kxY55gjQ==",
"dev": true,
"license": "MIT",
"engines": {
+1 -1
View File
@@ -1,3 +1,3 @@
*.LICENSE.txt
*.js
#webhooks
!ff/*/*.js
+1
View File
@@ -0,0 +1 @@
Options -Indexes
+98
View File
@@ -0,0 +1,98 @@
/*
* register.js
* Copyright (c) 2026 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/>.
*/
(function () {
const form = document.querySelector('form[action="'+route+'"]');
const errorBox = document.getElementById('client-errors');
const errorList = document.getElementById('client-errors-list');
const submitBtn = form.querySelector('button[type="submit"]');
const originalBtnText = submitBtn.textContent;
function showErrors(errors) {
errorList.innerHTML = errors.map(function(e) { return '<li>' + e + '</li>'; }).join('');
errorBox.style.display = 'block';
errorBox.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
async function sha1Hex(str) {
const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(str));
return Array.from(new Uint8Array(buf))
.map(function(b) { return b.toString(16).padStart(2, '0'); })
.join('')
.toUpperCase();
}
async function isPwned(password) {
const hash = await sha1Hex(password);
const prefix = hash.slice(0, 5);
const suffix = hash.slice(5);
const res = await fetch('https://api.pwnedpasswords.com/range/' + prefix, {
headers: { 'Add-Padding': 'true' }
});
if (!res.ok) { return false; }
const text = await res.text();
return text.toUpperCase().split('\n').some(function(line) {
return line.split(':')[0] === suffix;
});
}
form.addEventListener('submit', async function (e) {
e.preventDefault();
errorBox.style.display = 'none';
const password = form.querySelector('[name="password"]').value;
const confirm = form.querySelector('[name="password_confirmation"]').value;
const verify = form.querySelector('[name="verify_password"]');
const errors = [];
if (password.length < 16) {
errors.push(passwordLengthError);
}
if (password !== confirm) {
errors.push(passwordMatchError);
}
if (errors.length > 0) {
showErrors(errors);
return;
}
if (verify && verify.checked) {
submitBtn.disabled = true;
submitBtn.textContent = waitForVerify;
try {
if (await isPwned(password)) {
errors.push(needSecurePassword);
}
} catch (_) {
// network failure — let server validate
}
submitBtn.disabled = false;
submitBtn.textContent = originalBtnText;
}
if (errors.length > 0) {
showErrors(errors);
return;
}
form.submit();
});
})();
+1
View File
@@ -36,6 +36,7 @@
"/public/v1/js/ff/accounts/show.js": "/public/v1/js/ff/accounts/show.js",
"/public/v1/js/ff/admin/update/index.js": "/public/v1/js/ff/admin/update/index.js",
"/public/v1/js/ff/admin/users.js": "/public/v1/js/ff/admin/users.js",
"/public/v1/js/ff/auth/register.js": "/public/v1/js/ff/auth/register.js",
"/public/v1/js/ff/bills/create.js": "/public/v1/js/ff/bills/create.js",
"/public/v1/js/ff/bills/edit.js": "/public/v1/js/ff/bills/edit.js",
"/public/v1/js/ff/bills/index.js": "/public/v1/js/ff/bills/index.js",
+1
View File
@@ -23,6 +23,7 @@
declare(strict_types=1);
return [
'verifying_password' => 'Verifying password...',
'invalid_account_list' => 'Invalid account type list entry ":value"',
'invalid_transaction_type_list' => 'Invalid transaction type list',
'limit_exists' => 'There is already a budget limit (amount) for this budget and currency in the given period.',
+14 -3
View File
@@ -21,6 +21,10 @@
</div>
@endif
<div id="client-errors" class="alert alert-danger" role="alert" style="display:none;">
<ul id="client-errors-list"></ul>
</div>
<div class="card">
<div class="card-body register-card-body">
<p class="login-box-msg">{{ trans('firefly.register_new_account') }}</p>
@@ -35,11 +39,11 @@
</div>
<div class="input-group mb-3">
<input type="password" autocomplete="new-password" required class="form-control"
placeholder="{{ trans('form.password') }}" name="password"/>
placeholder="{{ trans('form.password') }}" minlength="16" name="password"/>
<div class="input-group-text"> <em class="fa-solid fa-lock"></em> </div>
</div>
<div class="input-group mb-3">
<input type="password" autocomplete="new-password" required class="form-control"
<input type="password" autocomplete="new-password" minlength="16" required class="form-control"
placeholder="{{ trans('form.password_confirmation') }}" name="password_confirmation"/>
<div class="input-group-text"> <em class="fa-solid fa-lock"></em> </div>
</div>
@@ -76,5 +80,12 @@
@endsection
@section('scripts')
@vite(['src/pages/dashboard/dashboard.js'])
<script nonce="{{ $JS_NONCE }}">
var route = '{{ route('register') }}';
var passwordLengthError = '{{ blade_escape_js((string)trans('validation.min.string', ['attribute' => 'password', 'min' => 16])) }}';
var passwordMatchError = '{{ blade_escape_js(trans('validation.confirmed', ['attribute' => 'password'])) }}';
var waitForVerify = '{{ blade_escape_js(trans('validation.verifying_password')) }}';
var needSecurePassword = '{{ blade_escape_js(trans('validation.secure_password')) }}';
</script>
<script nonce="{{$JS_NONCE}}" src="v1/js/ff/auth/register.js"></script>
@endsection
+3 -2
View File
@@ -32,8 +32,9 @@ if (!defined('DATEFORMAT')) {
// new Passport routes.
Route::group(
[
'as' => 'passport.',
'prefix' => 'oauth',
'as' => 'passport.',
'prefix' => 'oauth',
'middleware' => ['user-full-auth'],
// 'namespace' => 'FireflyIII\Http\Controllers\OAuth',
],
function (): void {