mirror of
https://github.com/opnsense/plugins.git
synced 2026-02-03 20:40:37 -05:00
Merge 037e1ba4c7 into c2c49fb1a1
This commit is contained in:
commit
fcbc12abc8
9 changed files with 482 additions and 14 deletions
|
|
@ -52,7 +52,11 @@ class AclController extends ApiMutableModelControllerBase
|
|||
|
||||
public function delAclAction($uuid)
|
||||
{
|
||||
return $this->delBase('acls.acl', $uuid);
|
||||
$del_tgt = $this->getBase('acl', 'acls.acl', $uuid);
|
||||
# skip if builtins...
|
||||
if (!($del_tgt['acl']['name'] == 'any' || $del_tgt['acl']['name'] == 'localnets' || $del_tgt['acl']['name'] == 'localhost' || $del_tgt['acl']['name'] == 'none')) {
|
||||
return $this->delBase('acls.acl', $uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public function setAclAction($uuid)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
<model>
|
||||
<mount>//OPNsense/bind/acl</mount>
|
||||
<description>BIND ACL configuration</description>
|
||||
<version>1.0.0</version>
|
||||
<version>1.0.1</version>
|
||||
<items>
|
||||
<acls>
|
||||
<acl type="ArrayField">
|
||||
<acl type=".\AclField">
|
||||
<enabled type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<name type="TextField">
|
||||
<Required>Y</Required>
|
||||
<Mask>/^(?!any$|localhost$|localnets$|none$)[0-9a-zA-Z_\-]{1,32}$/u</Mask>
|
||||
<ValidationMessage>Should be a string between 1 and 32 characters. Allowed characters are 0-9, a-z, A-Z, _ and -. Built-in ACL names must not be used: any, localhost, localnets, none.</ValidationMessage>
|
||||
<Mask>/^[0-9a-zA-Z_\-]{1,32}$/u</Mask>
|
||||
<ValidationMessage>Should be a string between 1 and 32 characters. Allowed characters are 0-9, a-z, A-Z, _ and -.</ValidationMessage>
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>An ACL with this name already exists.</ValidationMessage>
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
</check001>
|
||||
</Constraints>
|
||||
</name>
|
||||
<networks type="NetworkField">
|
||||
<networks type=".\AclNetField">
|
||||
<Required>Y</Required>
|
||||
<AsList>Y</AsList>
|
||||
</networks>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<model>
|
||||
<mount>//OPNsense/bind/domain</mount>
|
||||
<description>BIND domain configuration</description>
|
||||
<version>1.1.2</version>
|
||||
<version>1.1.3</version>
|
||||
<items>
|
||||
<domains>
|
||||
<domain type="ArrayField">
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
<domainname type="TextField">
|
||||
<Required>Y</Required>
|
||||
</domainname>
|
||||
<allowtransfer type="ModelRelationField">
|
||||
<allowtransfer type=".\AclModelRelationField">
|
||||
<Model>
|
||||
<template>
|
||||
<source>OPNsense.Bind.Acl</source>
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
<Multiple>Y</Multiple>
|
||||
</allowtransfer>
|
||||
<allowrndctransfer type="BooleanField"/>
|
||||
<allowquery type="ModelRelationField">
|
||||
<allowquery type=".\AclModelRelationField">
|
||||
<Model>
|
||||
<template>
|
||||
<source>OPNsense.Bind.Acl</source>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,163 @@
|
|||
<?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\BIND\FieldTypes;
|
||||
|
||||
use OPNsense\Base\FieldTypes\ArrayField;
|
||||
|
||||
class ACLField extends ArrayField
|
||||
{
|
||||
/*
|
||||
* Extends ArrayField to programmatically add BIND's builtin ACL types to
|
||||
* the model. The private property $internalTemplateNode is duplicated.
|
||||
* The actionPostLoadingEvent() method is replaced to add the builtin ACLs
|
||||
* as child nodes. The ability to add static children is removed. The builtin
|
||||
* ACL names are defined by the static $builtinNames property. Values for the
|
||||
* builtin ACLs are populated by the getBuiltinChildren() method. The public
|
||||
* function add() is also required.
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private $internalTemplateNode = null;
|
||||
|
||||
/**
|
||||
* @var list to define builtin BIND ACL names
|
||||
*/
|
||||
private static $builtinNames = ['none', 'localhost', 'localnets', 'any'];
|
||||
|
||||
/**
|
||||
* @return array of builtin BIND ACLs
|
||||
*/
|
||||
protected function getBuiltinChildren()
|
||||
{
|
||||
$builtins = [];
|
||||
foreach (self::$builtinNames as $aclName) {
|
||||
$builtins [] = [
|
||||
'enabled' => '1',
|
||||
'name' => $aclName,
|
||||
'networks' => 'system derived'
|
||||
];
|
||||
}
|
||||
return $builtins;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add($uuid = null)
|
||||
{
|
||||
$nodeUUID = empty($uuid) ? $this->generateUUID() : $uuid;
|
||||
$container_node = $this->newContainerField($this->__reference . "." . $nodeUUID, $this->internalXMLTagName);
|
||||
|
||||
$template_ref = $this->internalTemplateNode->__reference;
|
||||
foreach ($this->internalTemplateNode->iterateItems() as $key => $node) {
|
||||
$new_node = clone $node;
|
||||
$new_node->setInternalReference($container_node->__reference . "." . $key);
|
||||
$new_node->applyDefault();
|
||||
$new_node->setChanged();
|
||||
$container_node->addChildNode($key, $new_node);
|
||||
|
||||
if ($node->isContainer()) {
|
||||
foreach ($node->iterateRecursiveItems() as $subnode) {
|
||||
if (is_a($subnode, "OPNsense\\Base\\FieldTypes\\ArrayField")) {
|
||||
// validate child nodes, nesting not supported in this version.
|
||||
throw new \Exception("Unsupported copy, Array doesn't support nesting.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX: incomplete, only supports one nesting level of container fields. In the long run we probably
|
||||
* should refactor the add() function to push identifiers differently.
|
||||
*/
|
||||
foreach ($node->iterateItems() as $subkey => $subnode) {
|
||||
$new_subnode = clone $subnode;
|
||||
$new_subnode->setInternalReference($new_node->__reference . "." . $subkey);
|
||||
$new_subnode->applyDefault();
|
||||
$new_subnode->setChanged();
|
||||
$new_node->addChildNode($subkey, $new_subnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we have a UUID on repeating child items
|
||||
$container_node->setAttributeValue("uuid", $nodeUUID);
|
||||
|
||||
// add node to this object
|
||||
$this->addChildNode($nodeUUID, $container_node);
|
||||
|
||||
return $container_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function actionPostLoadingEvent()
|
||||
{
|
||||
// always make sure there's a node to copy our structure from
|
||||
if ($this->internalTemplateNode == null) {
|
||||
$firstKey = array_keys($this->internalChildnodes)[0];
|
||||
$this->internalTemplateNode = $this->internalChildnodes[$firstKey];
|
||||
/**
|
||||
* if first node is empty, remove reference node.
|
||||
*/
|
||||
if ($this->internalChildnodes[$firstKey]->getInternalIsVirtual()) {
|
||||
unset($this->internalChildnodes[$firstKey]);
|
||||
}
|
||||
}
|
||||
|
||||
// init builtin entries returned by getBuiltinChildren()
|
||||
foreach (static::getBuiltinChildren() as $skey => $payload) {
|
||||
$nodeUUID = $this->generateUUID();
|
||||
$container_node = $this->newContainerField($this->__reference . "." . $nodeUUID, $this->internalXMLTagName);
|
||||
$container_node->setAttributeValue("uuid", $nodeUUID);
|
||||
$template_ref = $this->internalTemplateNode->__reference;
|
||||
foreach ($this->internalTemplateNode->iterateItems() as $key => $value) {
|
||||
if ($key == 'name') {
|
||||
foreach ($this->iterateItems() as $pkey => $pnode) {
|
||||
foreach ($pnode->iterateItems() as $subkey => $subnode) {
|
||||
if ($subkey == 'name' && $subnode == $payload[$key]) {
|
||||
// The builtin ACL already exists, let's skip it...
|
||||
continue 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$node = clone $value;
|
||||
$node->setInternalReference($container_node->__reference . "." . $key);
|
||||
if (isset($payload[$key])) {
|
||||
$node->setValue($payload[$key]);
|
||||
}
|
||||
$node->setChanged();
|
||||
$container_node->addChildNode($key, $node);
|
||||
}
|
||||
$this->addChildNode($nodeUUID, $container_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-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\BIND\FieldTypes;
|
||||
|
||||
use OPNsense\Base\Validators\CallbackValidator;
|
||||
use OPNsense\Base\FieldTypes\BaseListField;
|
||||
use OPNsense\Base\FieldTypes\ModelRelationField;
|
||||
|
||||
class AclModelRelationField extends ModelRelationField
|
||||
{
|
||||
/*
|
||||
* Extends ModelRelationField but all private properties and the private
|
||||
* member loadModelOptions() require duplication. Public methods
|
||||
* getNodeData() and getValidators() are altered to use the grandparent
|
||||
* BaseListField:: rather than parent::. The getValidators() method is
|
||||
* also modified to call new isValidComboSelection() method via new
|
||||
* CallbackValidator(). We also require public methods actionPostLoadingEvent()
|
||||
* and setModel() too for this to work.
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private $internalIsSorted = false;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private $mdlStructure = null;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private $internalOptionsFromThisModel = false;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private $internalCacheKey = "";
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private static $internalCacheOptionList = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private static $internalCacheModelStruct = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
private function loadModelOptions($force = false)
|
||||
{
|
||||
// only collect options once per source/filter combination, we use a static to save our unique option
|
||||
// combinations over the running application.
|
||||
if (!isset(self::$internalCacheOptionList[$this->internalCacheKey]) || $force) {
|
||||
self::$internalCacheOptionList[$this->internalCacheKey] = [];
|
||||
foreach ($this->mdlStructure as $modelData) {
|
||||
// only handle valid model sources
|
||||
if (!isset($modelData['source']) || !isset($modelData['items']) || !isset($modelData['display'])) {
|
||||
continue;
|
||||
}
|
||||
$className = str_replace('.', '\\', $modelData['source']);
|
||||
$groupKey = isset($modelData['group']) ? $modelData['group'] : null;
|
||||
$displayKeys = explode(',', $modelData['display']);
|
||||
$displayFormat = !empty($modelData['display_format']) ? $modelData['display_format'] : "%s";
|
||||
|
||||
$searchItems = $this->getCachedData($className, $modelData['items'], $force);
|
||||
$groups = [];
|
||||
foreach ($searchItems as $uuid => $node) {
|
||||
$descriptions = [];
|
||||
foreach ($displayKeys as $displayKey) {
|
||||
$descriptions[] = $node['%' . $displayKey] ?? $node[$displayKey] ?? '';
|
||||
}
|
||||
if (isset($modelData['filters'])) {
|
||||
foreach ($modelData['filters'] as $filterKey => $filterValue) {
|
||||
$fieldData = $node[$filterKey] ?? null;
|
||||
if (!preg_match($filterValue, $fieldData) && $fieldData != null) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($groupKey)) {
|
||||
if (!isset($node[$groupKey]) || isset($groups[$node[$groupKey]])) {
|
||||
continue;
|
||||
}
|
||||
$groups[$node[$groupKey]] = 1;
|
||||
}
|
||||
self::$internalCacheOptionList[$this->internalCacheKey][$uuid] = vsprintf(
|
||||
$displayFormat,
|
||||
$descriptions
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->internalIsSorted) {
|
||||
natcasesort(self::$internalCacheOptionList[$this->internalCacheKey]);
|
||||
}
|
||||
}
|
||||
// Set for use in BaseListField->getNodeData()
|
||||
$this->internalOptionList = self::$internalCacheOptionList[$this->internalCacheKey];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setModel($mdlStructure)
|
||||
{
|
||||
// only handle array type input
|
||||
if (!is_array($mdlStructure)) {
|
||||
return;
|
||||
} else {
|
||||
$this->mdlStructure = $mdlStructure;
|
||||
// set internal key for this node based on sources and filter criteria
|
||||
$this->internalCacheKey = md5(serialize($mdlStructure));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function actionPostLoadingEvent()
|
||||
{
|
||||
$this->loadModelOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeData()
|
||||
{
|
||||
if ($this->internalIsSorted) {
|
||||
$optKeys = array_merge(explode(',', $this->internalValue), array_keys($this->internalOptionList));
|
||||
$ordered_option_list = [];
|
||||
foreach (array_unique($optKeys) as $key) {
|
||||
if (in_array($key, array_keys($this->internalOptionList))) {
|
||||
$ordered_option_list[$key] = $this->internalOptionList[$key];
|
||||
}
|
||||
}
|
||||
$this->internalOptionList = $ordered_option_list;
|
||||
}
|
||||
|
||||
return BaseListField::getNodeData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $input list of ACLs selected to validate
|
||||
* @return bool if valid combination of ACLs
|
||||
*/
|
||||
protected function isValidComboSelection($input)
|
||||
{
|
||||
if (strpos($input, ",") !== false) {
|
||||
// Pass validation if we only have a single-select.
|
||||
// Otherwise, get the ACL selection data and iterate to see if "any or "none" are included in the multi-select...
|
||||
$acls = $this->getNodeData();
|
||||
foreach ($acls as $node => $acl_sel_data) {
|
||||
if (($acl_sel_data['value'] == 'any' || $acl_sel_data['value'] == 'none') && $acl_sel_data['selected'] == '1') {
|
||||
$this->setValidationMessage("This ACL cannot be used in combination with others: " . $acl_sel_data['value']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValidators()
|
||||
{
|
||||
// Use validators from BaseListField, includes validations for multi-select, and single-select.
|
||||
$validators = BaseListField::getValidators();
|
||||
if ($this->internalValue != null) {
|
||||
// XXX: may be improved a bit to prevent the same object being constructed multiple times when used
|
||||
// in different fields (passing of $force parameter)
|
||||
$this->loadModelOptions($this->internalOptionsFromThisModel);
|
||||
$that = $this;
|
||||
$validators[] = new CallbackValidator(["callback" => function ($data) use ($that) {
|
||||
$messages = [];
|
||||
if (!$that->isValidComboSelection($data)) {
|
||||
$messages[] = $this->getValidationMessage();
|
||||
}
|
||||
return $messages;
|
||||
}]);
|
||||
}
|
||||
return $validators;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?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\BIND\FieldTypes;
|
||||
|
||||
use OPNsense\Base\Validators\CallbackValidator;
|
||||
use OPNsense\Base\FieldTypes\BaseSetField;
|
||||
use OPNsense\Base\FieldTypes\NetworkField;
|
||||
|
||||
class ACLNetField extends NetworkField
|
||||
{
|
||||
/*
|
||||
* Extends the NetworkField getValidators() method to ignore networks specified
|
||||
* as 'system defined', which is the value used to describe BIND's builtin ACLs.
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValidators()
|
||||
{
|
||||
$validators = BaseSetField::getValidators();
|
||||
if ($this->internalValue != null) {
|
||||
if ($this->internalValue != "any" || $this->internalWildcardEnabled == false) {
|
||||
$that = $this;
|
||||
$validators[] = new CallbackValidator(["callback" => function ($data) use ($that) {
|
||||
$messages = [];
|
||||
if ($data == 'system derived' ) {
|
||||
// ignoring builtin BIND ACL names
|
||||
} elseif (!$that->isValidInput($data)) {
|
||||
$messages[] = $this->getValidationMessage();
|
||||
}
|
||||
return $messages;
|
||||
}]);
|
||||
}
|
||||
}
|
||||
return $validators;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<model>
|
||||
<mount>//OPNsense/bind/general</mount>
|
||||
<description>BIND configuration</description>
|
||||
<version>1.0.12</version>
|
||||
<version>1.0.13</version>
|
||||
<items>
|
||||
<enabled type="BooleanField">
|
||||
<Default>0</Default>
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
<MaximumValue>99</MaximumValue>
|
||||
<ValidationMessage>Choose a value between 1 and 99.</ValidationMessage>
|
||||
</maxcachesize>
|
||||
<recursion type="ModelRelationField">
|
||||
<recursion type=".\AclModelRelationField">
|
||||
<Model>
|
||||
<template>
|
||||
<source>OPNsense.Bind.Acl</source>
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
<Multiple>Y</Multiple>
|
||||
<ValidationMessage>Choose an ACL.</ValidationMessage>
|
||||
</recursion>
|
||||
<allowtransfer type="ModelRelationField">
|
||||
<allowtransfer type=".\AclModelRelationField">
|
||||
<Model>
|
||||
<template>
|
||||
<source>OPNsense.Bind.Acl</source>
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
</Model>
|
||||
<Multiple>Y</Multiple>
|
||||
</allowtransfer>
|
||||
<allowquery type="ModelRelationField">
|
||||
<allowquery type=".\AclModelRelationField">
|
||||
<Model>
|
||||
<template>
|
||||
<source>OPNsense.Bind.Acl</source>
|
||||
|
|
|
|||
|
|
@ -397,7 +397,26 @@ $(document).ready(function() {
|
|||
'set': '/api/bind/acl/set_acl/',
|
||||
'add': '/api/bind/acl/add_acl/',
|
||||
'del': '/api/bind/acl/del_acl/',
|
||||
'toggle': '/api/bind/acl/toggle_acl/'
|
||||
'toggle': '/api/bind/acl/toggle_acl/',
|
||||
options: {
|
||||
formatters: {
|
||||
"commands": function (column, row) {
|
||||
// Disable the command buttons for builtin ACLs
|
||||
if (row.networks === "system derived") {
|
||||
return "<button type=\"button\" class=\"btn btn-xs btn-default bootgrid-tooltip command-edit\" data-row-id=\"" + row.uuid + "\" title=\"\" aria-label=\"Edit\" data-original-title=\"Edit\" disabled=\"disabled\"><span class=\"fa fa-fw fa-pencil\"></span></button> " +
|
||||
"<button type=\"button\" class=\"btn btn-xs btn-default bootgrid-tooltip command-copy\" data-row-id=\"" + row.uuid + "\" title=\"\" aria-label=\"Clone\" data-original-title=\"Clone\" disabled=\"disabled\"><span class=\"fa fa-fw fa-clone\"></span></button> " +
|
||||
"<button type=\"button\" class=\"btn btn-xs btn-default bootgrid-tooltip command-delete\" data-row-id=\"" + row.uuid + "\" title=\"\" aria-label=\"Delete\" data-original-title=\"Delete\" disabled=\"disabled\"><span class=\"fa fa-fw fa-trash-o\"></span></button>";
|
||||
} else {
|
||||
return "<button type=\"button\" class=\"btn btn-xs btn-default bootgrid-tooltip command-edit\" data-row-id=\"" + row.uuid + "\" title=\"\" aria-label=\"Edit\" data-original-title=\"Edit\"><span class=\"fa fa-fw fa-pencil\"></span></button> " +
|
||||
"<button type=\"button\" class=\"btn btn-xs btn-default bootgrid-tooltip command-copy\" data-row-id=\"" + row.uuid + "\" title=\"\" aria-label=\"Clone\" data-original-title=\"Clone\"><span class=\"fa fa-fw fa-clone\"></span></button> " +
|
||||
"<button type=\"button\" class=\"btn btn-xs btn-default bootgrid-tooltip command-delete\" data-row-id=\"" + row.uuid + "\" title=\"\" aria-label=\"Delete\" data-original-title=\"Delete\"><span class=\"fa fa-fw fa-trash-o\"></span></button>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).on("loaded.rs.jquery.bootgrid", function(e) {
|
||||
// always save on load to ensure the builtin ACLs are in config.xml
|
||||
saveFormToEndpoint(url = "/api/bind/acl/set", formid = 'frm_general_settings');
|
||||
});
|
||||
|
||||
$("#grid-primary-domains").UIBootgrid({
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
{% if helpers.exists('OPNsense.bind.acl.acls.acl') %}
|
||||
{% for acl_list in helpers.toList('OPNsense.bind.acl.acls.acl') %}
|
||||
{% if acl_list.enabled == '1' %}
|
||||
{% if not (acl_list.name == 'none' or acl_list.name == 'localhost' or acl_list.name == 'localnets' or acl_list.name == 'any') %}
|
||||
acl "{{ acl_list.name }}" { {{ acl_list.networks.replace(',', '; ') }}; };
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
|
|
|||
Loading…
Reference in a new issue