Skip to content

Commit

Permalink
wizard: reimplement system setup, for #8352
Browse files Browse the repository at this point in the history
  • Loading branch information
AdSchellevis committed Feb 20, 2025
1 parent 3caf9e1 commit 2b47514
Show file tree
Hide file tree
Showing 7 changed files with 334 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* Copyright (c) 2025 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

namespace OPNsense\Core\Api;

use OPNsense\Base\ApiMutableModelControllerBase;
use OPNsense\Core\Backend;

/**
* Class InitialSetupController
* @package OPNsense\Core
*/
class InitialSetupController extends ApiMutableModelControllerBase
{
protected static $internalModelName = 'wizard';
protected static $internalModelClass = 'OPNsense\Core\InitialSetup';

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

/**
* Copyright (C) 2025 Deciso B.V.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/

namespace OPNsense\Core;

class InitialSetupController extends \OPNsense\Base\IndexController
{
public function indexAction()
{
$this->view->all_tabs = [
'step_0' => [
'title' => gettext('Welcome'),
'message' => gettext(
'This wizard will guide you through the initial system configuration. '.
'The wizard may be stopped at any time by clicking the logo image at the top of the screen.'
)
],
'step_1' => [
'title' => gettext('General Information'),
'form' => $this->getForm('wizard_general_info')
],
'step_2' => [
'title' => gettext('Network [WAN]'),
'form' => $this->getForm('wizard_network_wan')
]
];
$this->view->pick('OPNsense/Core/initial_setup');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<form>
<field>
<id>wizard.hostname</id>
<label>Hostname</label>
<type>text</type>
</field>
<field>
<id>wizard.domain</id>
<label>Domain</label>
<type>text</type>
</field>
<field>
<id>wizard.language</id>
<label>Languaga</label>
<type>dropdown</type>
</field>
<field>
<id>wizard.dns_servers</id>
<label>DNS Servers</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
<help>Set primary domain name server IPv4 or IPv6 address. Repeat this option to set secondary DNS server addresses.</help>
</field>
<field>
<id>wizard.language</id>
<label>Languaga</label>
<type>dropdown</type>
</field>
<field>
<id>wizard.dnsallowoverride</id>
<label>Override DNS</label>
<type>checkbox</type>
<help>Allow DNS servers to be overridden by DHCP/PPP on WAN</help>
</field>
<field>
<type>header</type>
<label>Unbound DNS</label>
</field>
<field>
<id>wizard.unbound.enabled</id>
<label>Enable Resolver</label>
<type>checkbox</type>
</field>
<field>
<id>wizard.unbound.dnssec</id>
<label>Enable DNSSEC Support</label>
<type>checkbox</type>
</field>
<field>
<id>wizard.unbound.dnssecstripped</id>
<label>Harden DNSSEC data</label>
<type>checkbox</type>
<help>DNSSEC data is required for trust-anchored zones. If such data is absent, the zone becomes bogus. If this is disabled and no DNSSEC data is received, then the zone is made insecure.</help>
</field>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<form>

</form>
70 changes: 70 additions & 0 deletions src/opnsense/mvc/app/models/OPNsense/Core/InitialSetup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

/*
* Copyright (C) 2025 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

namespace OPNsense\Core;

use OPNsense\Base\BaseModel;
use OPNsense\Core\Config;

class InitialSetup extends BaseModel
{

private function getConfigItem(string $path)
{
$node = Config::getInstance()->object();
foreach(explode('.', $path) as $item) {
if (isset($node->$item)) {
$node = $node->$item;
} else {
return '';
}
}
if (count($node) > 1) {
$tmp = [];
foreach ($node as $item) {
$tmp[] = (string)$item;
}
return implode(',', $tmp);
}
return (string)$node;
}

/**
* setup initial values
*/
protected function init()
{
$this->hostname = $this->getConfigItem('system.hostname');
$this->domain = $this->getConfigItem('system.domain');
$this->language = $this->getConfigItem('system.language');
$this->dns_servers = $this->getConfigItem('system.dnsserver');
$this->unbound->enabled = $this->getConfigItem('OPNsense.unboundplus.general.enabled');
$this->unbound->dnssec = $this->getConfigItem('OPNsense.unboundplus.general.dnssec');
$this->unbound->dnssecstripped = $this->getConfigItem('OPNsense.unboundplus.advanced.dnssecstripped');
}
}
40 changes: 40 additions & 0 deletions src/opnsense/mvc/app/models/OPNsense/Core/InitialSetup.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<model>
<mount>:memory:</mount>
<version>1.0.0</version>
<description>Initial setup wizard</description>
<items>
<hostname type="HostnameField">
<IsDNSName>N</IsDNSName>
<IpAllowed>N</IpAllowed>
<Required>Y</Required>
</hostname>
<domain type="HostnameField">
<IsDNSName>N</IsDNSName>
<IpAllowed>N</IpAllowed>
<Required>Y</Required>
</domain>
<language type="JsonKeyValueStoreField">
<ConfigdPopulateAct>system list locales</ConfigdPopulateAct>
<Required>Y</Required>
</language>
<dns_servers type="NetworkField">
<NetMaskAllowed>N</NetMaskAllowed>
<FieldSeparator>,</FieldSeparator>
<asList>Y</asList>
</dns_servers>
<dnsallowoverride type="BooleanField">
<Required>Y</Required>
</dnsallowoverride>
<unbound>
<enabled type="BooleanField">
<Required>Y</Required>
</enabled>
<dnssec type="BooleanField">
<Required>Y</Required>
</dnssec>
<dnssecstripped type="BooleanField">
<Required>Y</Required>
</dnssecstripped>
</unbound>
</items>
</model>
66 changes: 66 additions & 0 deletions src/opnsense/mvc/app/views/OPNsense/Core/initial_setup.volt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<script>
$( document ).ready(function() {
mapDataToFormUI({'frm_wizard':"/api/core/initial_setup/get"}).done(function(data){
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
});
/* next pane */
$(".action_next").click(function(){
let target = $("#tab_" + $(this).data('next_index'));
let this_form = $(this).closest('.tab-pane').find('form');
saveFormToEndpoint("/api/core/initial_setup/set", 'form_root', function(){
target.parent().removeClass('hidden');
target.click();
},
true,
function (data) {
let failed_here = false;
if (data.validations && this_form) {
let validations = Object.keys(data.validations);
this_form.find('input').each(function(){
if (validations.includes($(this).attr('id'))) {
failed_here = true;
}
});
}
if (!failed_here) {
target.parent().removeClass('hidden');
target.click();
}
});
});
});
</script>

<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
{% for tabid, tab in all_tabs%}
<li class="{% if loop.first %}active{% else %}hidden{% endif %}"><a data-toggle="tab" id="tab_{{loop.index}}" href="#{{tabid}}">{{ tab['title'] }}</a></li>
{% endfor %}
</ul>
<div class="tab-content content-box" id="form_root">
{% for tabid, tab in all_tabs%}
<div id="{{tabid}}" class="tab-pane fade in {% if loop.first %}active{% endif %}" style="padding-top:10px;">
<div class="col-md-12">
{% if tab['message'] is defined %}
<div class="well">
{{ tab['message'] }}
</div>
{% elseif tab['form'] is defined %}
{{ partial("layout_partials/base_form",['fields': tab['form'], 'id': 'frm_wizard-' ~ tabid ])}}
<br/>
{% endif %}

{% if not loop.last %}
<button class="btn btn-primary action_next" id="btn_next_{{loop.index}}" data-next_index="{{loop.index + 1}}">
{{ lang._('Next') }}
</button>
{% else %}
<button class="btn btn-primary" id="apply">
{{ lang._('Apply') }}
</button>
{% endif %}
<br/><br/>
</div>
</div>
{% endfor %}
</div>

0 comments on commit 2b47514

Please sign in to comment.