Move settings to the settings page, out of the .env file.

This commit is contained in:
James Cole
2025-12-20 06:39:05 +01:00
parent be9078fe99
commit 71c5bdb198
5 changed files with 195 additions and 48 deletions

View File

@@ -23,11 +23,11 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Admin; namespace FireflyIII\Http\Controllers\Admin;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Http\Requests\ConfigurationRequest; use FireflyIII\Http\Requests\ConfigurationRequest;
use FireflyIII\Support\Facades\FireflyConfig; use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -47,7 +47,7 @@ class ConfigurationController extends Controller
$this->middleware( $this->middleware(
static function ($request, $next) { static function ($request, $next) {
app('view')->share('title', (string) trans('firefly.system_settings')); app('view')->share('title', (string)trans('firefly.system_settings'));
app('view')->share('mainTitleIcon', 'fa-hand-spock-o'); app('view')->share('mainTitleIcon', 'fa-hand-spock-o');
return $next($request); return $next($request);
@@ -61,10 +61,10 @@ class ConfigurationController extends Controller
* *
* @return Factory|View * @return Factory|View
*/ */
public function index(): Factory|\Illuminate\Contracts\View\View public function index(): Factory | \Illuminate\Contracts\View\View
{ {
$subTitle = (string) trans('firefly.instance_configuration'); $subTitle = (string)trans('firefly.instance_configuration');
$subTitleIcon = 'fa-wrench'; $subTitleIcon = 'fa-wrench';
Log::channel('audit')->info('User visits admin config index.'); Log::channel('audit')->info('User visits admin config index.');
@@ -74,9 +74,28 @@ class ConfigurationController extends Controller
$isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data; $isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
$siteOwner = config('firefly.site_owner'); $siteOwner = config('firefly.site_owner');
$enableExchangeRates = FireflyConfig::get('enable_exchange_rates', config('cer.enabled'))->data;
$useRunningBalance = FireflyConfig::get('use_running_balance', config('firefly.feature_flags.running_balance_column'))->data;
$enableExternalMap = FireflyConfig::get('enable_external_map', config('firefly.enable_external_map'))->data;
$enableExternalRates = FireflyConfig::get('enable_external_rates', config('cer.download_enabled'))->data;
$allowWebhooks = FireflyConfig::get('allow_webhooks', config('firefly.allow_webhooks'))->data;
$validUrlProtocols = FireflyConfig::get('valid_url_protocols', config('firefly.valid_url_protocols'))->data;;
return view( return view(
'settings.configuration.index', 'settings.configuration.index',
['subTitle' => $subTitle, 'subTitleIcon' => $subTitleIcon, 'singleUserMode' => $singleUserMode, 'isDemoSite' => $isDemoSite, 'siteOwner' => $siteOwner] [
'subTitle' => $subTitle,
'subTitleIcon' => $subTitleIcon,
'singleUserMode' => $singleUserMode,
'isDemoSite' => $isDemoSite,
'siteOwner' => $siteOwner,
'enableExchangeRates' => $enableExchangeRates,
'useRunningBalance' => $useRunningBalance,
'enableExternalMap' => $enableExternalMap,
'enableExternalRates' => $enableExternalRates,
'allowWebhooks' => $allowWebhooks,
'validUrlProtocols' => $validUrlProtocols,
]
); );
} }
@@ -92,10 +111,19 @@ class ConfigurationController extends Controller
// store config values // store config values
FireflyConfig::set('single_user_mode', $data['single_user_mode']); FireflyConfig::set('single_user_mode', $data['single_user_mode']);
FireflyConfig::set('enable_exchange_rates', $data['enable_exchange_rates']);
FireflyConfig::set('use_running_balance', $data['use_running_balance']);
FireflyConfig::set('enable_external_map', $data['enable_external_map']);
FireflyConfig::set('enable_external_rates', $data['enable_external_rates']);
FireflyConfig::set('allow_webhooks', $data['allow_webhooks']);
FireflyConfig::set('valid_url_protocols', $data['valid_url_protocols']);
FireflyConfig::set('is_demo_site', $data['is_demo_site']); FireflyConfig::set('is_demo_site', $data['is_demo_site']);
// flash message // flash message
session()->flash('success', (string) trans('firefly.configuration_updated')); session()->flash('success', (string)trans('firefly.configuration_updated'));
Preferences::mark(); Preferences::mark();
return redirect()->route('settings.configuration.index'); return redirect()->route('settings.configuration.index');

View File

@@ -23,8 +23,8 @@ declare(strict_types=1);
namespace FireflyIII\Http\Requests; namespace FireflyIII\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ChecksLogin;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -42,7 +42,16 @@ class ConfigurationRequest extends FormRequest
{ {
return [ return [
'single_user_mode' => $this->boolean('single_user_mode'), 'single_user_mode' => $this->boolean('single_user_mode'),
'is_demo_site' => $this->boolean('is_demo_site'),
'enable_exchange_rates' => $this->boolean('enable_exchange_rates'),
'use_running_balance' => $this->boolean('use_running_balance'),
'enable_external_map' => $this->boolean('enable_external_map'),
'enable_external_rates' => $this->boolean('enable_external_rates'),
'allow_webhooks' => $this->boolean('allow_webhooks'),
'valid_url_protocols' => $this->string('valid_url_protocols'),
'is_demo_site' => $this->boolean('is_demo_site'),
]; ];
} }
@@ -54,7 +63,18 @@ class ConfigurationRequest extends FormRequest
// fixed // fixed
return [ return [
'single_user_mode' => 'min:0|max:1|numeric', 'single_user_mode' => 'min:0|max:1|numeric',
'is_demo_site' => 'min:0|max:1|numeric',
'enable_exchange_rates' => 'min:0|max:1|numeric',
'use_running_balance' => 'min:0|max:1|numeric',
'enable_external_map' => 'min:0|max:1|numeric',
'enable_external_rates' => 'min:0|max:1|numeric',
'allow_webhooks' => 'min:0|max:1|numeric',
'valid_url_protocols' => 'min:0|max:255',
'is_demo_site' => 'min:0|max:1|numeric',
]; ];
} }

View File

@@ -2567,6 +2567,25 @@ return [
'all_users' => 'All users', 'all_users' => 'All users',
'instance_configuration' => 'Configuration', 'instance_configuration' => 'Configuration',
'firefly_instance_configuration' => 'Firefly III configuration', 'firefly_instance_configuration' => 'Firefly III configuration',
'config_security' => 'Security configuration',
'config_features' => 'Enabled features',
'config_tech' => 'Tech related features',
'config_external_connections' => 'Privacy-sensitive settings (connects to the internet)',
'setting_enable_exchange_rates' => 'Enable exchange rates',
'setting_enable_exchange_rates_explain' => 'Firefly III has the capability of calculating exchange rates for you.',
'setting_use_running_balance' => 'Use "running balance"-column and data',
'setting_use_running_balance_explain' => 'Firefly III can calculate the current running balance for you, and display this in various places. It is still slightly experimental, so disabled by default. You may need to restart your container or fire the initial command manually (see the docs).',
'setting_enable_external_map' => 'Use external map service',
'setting_enable_external_map_explain' => 'Firefly III uses an external service to display locations. Is this OK?',
'setting_enable_external_rates' => 'Download exchange rates from the web',
'setting_enable_external_rates_explain' => 'Firefly III can download exchange rates for the built-in currencies. This needs the cron job to work.',
'setting_allow_webhooks' => 'Allow webhooks',
'setting_allow_webhooks_explain' => 'Allow Firefly III to fire webhooks?',
'setting_valid_url_protocols' => 'Allowed URL protocols',
'setting_valid_url_protocols_explain' => 'Firefly III only allows urls to have standard protocols like https and ftp etc. If you\'re a techie you may want to allow others as well.',
'setting_single_user_mode' => 'Single user mode', 'setting_single_user_mode' => 'Single user mode',
'setting_single_user_mode_explain' => 'By default, Firefly III only accepts one (1) registration: you. This is a security measure, preventing others from using your instance unless you allow them to. Future registrations are blocked. When you uncheck this box, others can use your instance as well, assuming they can reach it (when it is connected to the internet).', 'setting_single_user_mode_explain' => 'By default, Firefly III only accepts one (1) registration: you. This is a security measure, preventing others from using your instance unless you allow them to. Future registrations are blocked. When you uncheck this box, others can use your instance as well, assuming they can reach it (when it is connected to the internet).',
'store_configuration' => 'Store configuration', 'store_configuration' => 'Store configuration',

View File

@@ -67,9 +67,12 @@ return [
'tag_mode' => 'Tag mode', 'tag_mode' => 'Tag mode',
'virtual_balance' => 'Virtual balance', 'virtual_balance' => 'Virtual balance',
'run_after_form' => 'Run this rule', 'run_after_form' => 'Run this rule',
'valid_url_protocols' => 'Valid URL protocols',
'allow_webhooks' => 'Allow webhooks',
'enable_external_rates' => 'Enable external exchange rates',
'enable_external_map' => 'Enable external map',
'use_running_balance' => 'Calculate running balances',
'enable_exchange_rates' => 'Enable exchange rates',
'targetamount' => 'Target amount', 'targetamount' => 'Target amount',
'target_amount' => 'Target amount', 'target_amount' => 'Target amount',
'account_role' => 'Account role', 'account_role' => 'Account role',

View File

@@ -4,66 +4,143 @@
{{ Breadcrumbs.render }} {{ Breadcrumbs.render }}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<!--
Security
- single user mode
Features
- enable exchange rates
- use running balance
External connections
- enable external map
- enable external exchange rates
- allow webhooks
Technical stuff
- valid url protocols
- is demo site
-->
<form action="{{ route('settings.configuration.index.post') }}" method="post" id="store" class="form-horizontal"> <form action="{{ route('settings.configuration.index.post') }}" method="post" id="store" class="form-horizontal">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
{# security #}
<div class="row"> <div class="row">
<div class="col-lg-8 col-lg-offset-2 col-xl-8 col-xl-offset-2 col-md-12 col-sm-12 col-xs-12">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
{# single user mode #}
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
<div class="box box-default"> <div class="box box-default">
<div class="box-header with-border"> <div class="box-header with-border">
<h3 class="box-title">{{ 'setting_single_user_mode'|_ }}</h3> <h3 class="box-title">{{ 'config_security'|_ }}</h3>
</div> </div>
<div class="box-body"> <div class="box-body">
<p class="text-info"> <h4>
{{ 'setting_single_user_mode'|_ }}
</h4>
<p>
{{ 'setting_single_user_mode_explain'|_ }} {{ 'setting_single_user_mode_explain'|_ }}
</p> </p>
{{ ExpandedForm.checkbox('single_user_mode','1', singleUserMode) }} {{ ExpandedForm.checkbox('single_user_mode','1', singleUserMode) }}
</div> </div>
</div> </div>
</div> </div>
</div>
{# installation is demo site #} <div class="row">
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12"> <div class="col-lg-8 col-lg-offset-2 col-xl-8 col-xl-offset-2 col-md-12 col-sm-12 col-xs-12">
<div class="box box-default"> <div class="box box-default">
<div class="box-header with-border"> <div class="box-header with-border">
<h3 class="box-title">{{ 'setting_is_demo_site'|_ }}</h3> <h3 class="box-title">{{ 'config_features'|_ }}</h3>
</div> </div>
<div class="box-body"> <div class="box-body">
<p class="text-info"> <h4>
{{ 'setting_enable_exchange_rates'|_ }}
</h4>
<p>
{{ 'setting_enable_exchange_rates_explain'|_ }}
</p>
{{ ExpandedForm.checkbox('enable_exchange_rates','1', enableExchangeRates) }}
<h4>
{{ 'setting_use_running_balance'|_ }}
</h4>
<p>
{{ 'setting_use_running_balance_explain'|_ }}
</p>
{{ ExpandedForm.checkbox('use_running_balance','1', useRunningBalance) }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-xl-8 col-xl-offset-2 col-md-12 col-sm-12 col-xs-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ 'config_external_connections'|_ }}</h3>
</div>
<div class="box-body">
<h4>
{{ 'setting_enable_external_map'|_ }}
</h4>
<p>
{{ 'setting_enable_external_map_explain'|_ }}
</p>
{{ ExpandedForm.checkbox('enable_external_map','1', enableExternalMap) }}
<h4>
{{ 'setting_enable_external_rates'|_ }}
</h4>
<p>
{{ 'setting_enable_external_rates_explain'|_ }}
</p>
{{ ExpandedForm.checkbox('enable_external_rates','1', enableExternalRates) }}
<h4>
{{ 'setting_allow_webhooks'|_ }}
</h4>
<p>
{{ 'setting_allow_webhooks_explain'|_ }}
</p>
{{ ExpandedForm.checkbox('allow_webhooks','1', allowWebhooks) }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-xl-8 col-xl-offset-2 col-md-12 col-sm-12 col-xs-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ 'config_tech'|_ }}</h3>
</div>
<div class="box-body">
<h4>
{{ 'setting_valid_url_protocols'|_ }}
</h4>
<p>
{{ 'setting_valid_url_protocols_explain'|_ }}
</p>
{{ ExpandedForm.text('valid_url_protocols', validUrlProtocols) }}
<h4>
{{ 'setting_is_demo_site'|_ }}
</h4>
<p>
{{ 'setting_is_demo_site_explain'|_ }} {{ 'setting_is_demo_site_explain'|_ }}
</p> </p>
{{ ExpandedForm.checkbox('is_demo_site','1', isDemoSite) }} {{ ExpandedForm.checkbox('is_demo_site','1', isDemoSite) }}
</div> <p>
</div> <button type="submit" class="btn btn-success">
</div> {{ ('store_configuration')|_ }}
</button>
{# block for config setting #}
{#
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ 'setting_x'|_ }}</h3>
</div>
<div class="box-body">
<p class="text-info">
{{ 'setting_x_explain'|_ }}
</p> </p>
</div> </div>
</div> </div>
</div> </div>
#}
</div> </div>
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
<button type="submit" class="btn btn-success">
{{ ('store_configuration')|_ }}
</button>
</div>
</div>
</form> </form>
{% endblock %} {% endblock %}