treewide: switch firewall zone, network and iface lists to dropdown code

Also switch the weekday and monthday lists in the firewall rule details to
cbi dropdowns, vastly uncluttering the form.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2018-06-08 08:19:20 +02:00
parent 9d48490729
commit 74be6f3974
9 changed files with 190 additions and 180 deletions

View file

@ -55,6 +55,7 @@ o = s:option(Value, "src", translate("Source zone"))
o.nocreate = true
o.default = "wan"
o.template = "cbi/firewall_zonelist"
o.rmempty = false
o = s:option(DynamicList, "src_mac",

View file

@ -255,7 +255,7 @@ else
o = s:option(Value, "src", translate("Source zone"))
o.nocreate = true
o.allowany = true
o.default = "wan"
o.allowlocal = "src"
o.template = "cbi/firewall_zonelist"
@ -282,11 +282,21 @@ else
o.placeholder = translate("any")
o = s:option(Value, "dest", translate("Destination zone"))
o = s:option(Value, "dest_local", translate("Output zone"))
o.nocreate = true
o.allowany = true
o.rmempty = false
o.template = "cbi/firewall_zonelist"
o.alias = "dest"
o:depends("src", "")
o = s:option(Value, "dest_remote", translate("Destination zone"))
o.nocreate = true
o.allowany = true
o.allowlocal = true
o.template = "cbi/firewall_zonelist"
o.alias = "dest"
o:depends({["src"] = "", ["!reverse"] = true})
o = s:option(Value, "dest_ip", translate("Destination address"))
@ -316,9 +326,9 @@ else
translate("Passes additional arguments to iptables. Use with care!"))
end
o = s:option(MultiValue, "weekdays", translate("Week Days"))
o.oneline = true
o.widget = "checkbox"
o = s:option(DropDown, "weekdays", translate("Week Days"))
o.multiple = true
o.display = 5
o:value("Sun", translate("Sunday"))
o:value("Mon", translate("Monday"))
o:value("Tue", translate("Tuesday"))
@ -327,9 +337,9 @@ o:value("Thu", translate("Thursday"))
o:value("Fri", translate("Friday"))
o:value("Sat", translate("Saturday"))
o = s:option(MultiValue, "monthdays", translate("Month Days"))
o.oneline = true
o.widget = "checkbox"
o = s:option(DropDown, "monthdays", translate("Month Days"))
o.multiple = true
o.display = 15
for i = 1,31 do
o:value(translate(i))
end

View file

@ -101,9 +101,12 @@ end
function net.write(self, section, value)
zone:clear_networks()
local n
for n in ut.imatch(value) do
zone:add_network(n)
local net
for net in ut.imatch(value) do
local n = nw:get_network(net) or nw:add_network(net, { proto = "none" })
if n then
zone:add_network(n:name())
end
end
end

View file

@ -24,26 +24,42 @@
end
-%>
<span>
<ul style="margin:0; list-style-type:none; text-align:left">
<div class="cbi-dropdown" dropdown-items="5" placeholder="<%:-- please select -- %>"<%=
attr("name", cbid) ..
ifattr(self.widget == "checkbox", "multiple", "multiple") ..
ifattr(self.rmempty or self.optional, "optional", "optional")
%>>
<script type="item-template"><!--
<li value="{{value}}">
<span class="zonebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">
<strong>{{value}}:</strong><em>(<%:create%>)</em>
</span>
</li>
--></script>
<ul>
<% if self.allowlocal then %>
<li style="padding:0.5em">
<input class="cbi-input-radio" data-update="click change"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "_empty") .. attr("name", cbid) .. attr("value", "") .. ifattr(checked[""], "checked", "checked")%> /> &#160;
<label<%=attr("for", cbid .. "_empty")%>></label>
<label<%=attr("for", cbid .. "_empty")%> style="background-color:<%=fwm.zone.get_color()%>" class="zonebadge">
<li value=""<%=ifattr(checked[""], "selected", "selected")%>>
<span style="background-color:<%=fwm.zone.get_color()%>" class="zonebadge">
<strong><%:Device%></strong>
<% if self.allowany and self.allowlocal then %>(<%:input%>)<% end %>
</label>
<% if self.allowany and self.allowlocal then -%>
(<%= self.alias ~= "dest"
and translate("output") or translate("input") %>)
<%- end %>
</span>
</li>
<% elseif self.widget ~= "checkbox" and (self.rmempty or self.optional) then %>
<li value=""<%=ifattr(checked[""], "selected", "selected")%>>
<span class="zonebadge">
<em><%:unspecified%></em>
</span>
</li>
<% end %>
<% if self.allowany then %>
<li style="padding:0.5em">
<input class="cbi-input-radio" data-update="click change"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "_any") .. attr("name", cbid) .. attr("value", "*") .. ifattr(checked["*"], "checked", "checked")%> /> &#160;
<label<%=attr("for", cbid .. "_any")%>></label>
<label<%=attr("for", cbid .. "_any")%> style="background-color:<%=fwm.zone.get_color()%>" class="zonebadge">
<li value="*"<%=ifattr(checked["*"], "selected", "selected")%>>
<span style="background-color:<%=fwm.zone.get_color()%>" class="zonebadge">
<strong><%:Any zone%></strong>
<% if self.allowany and self.allowlocal then %>(<%:forward%>)<% end %>
</label>
</span>
</li>
<% end %>
<%
@ -51,45 +67,42 @@
if zone:name() ~= self.exclude then
selected = selected or (value == zone:name())
%>
<li style="padding:0.5em">
<input class="cbi-input-radio" data-update="click change"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "." .. zone:name()) .. attr("name", cbid) .. attr("value", zone:name()) .. ifattr(checked[zone:name()], "checked", "checked")%> /> &#160;
<label<%=attr("for", cbid .. "." .. zone:name())%>></label>
<label<%=attr("for", cbid .. "." .. zone:name())%> style="background-color:<%=zone:get_color()%>" class="zonebadge">
<li<%=attr("value", zone:name()) .. ifattr(checked[zone:name()], "selected", "selected")%>>
<span style="background-color:<%=zone:get_color()%>" class="zonebadge">
<strong><%=zone:name()%>:</strong>
<%
<%-
local zempty = true
for _, net in ipairs(zone:get_networks()) do
net = nwm:get_network(net)
if net then
zempty = false
%>
-%>
<span class="ifacebadge<% if net:name() == self.network then %> ifacebadge-active<% end %>"><%=net:name()%>:
<%
<%-
local nempty = true
for _, iface in ipairs(net:is_bridge() and net:get_interfaces() or { net:get_interface() }) do
nempty = false
%>
<img<%=attr("title", iface:get_i18n())%> style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" />
<img<%=attr("title", iface:get_i18n())%> src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" />
<% end %>
<% if nempty then %><em><%:(empty)%></em><% end %>
<% if nempty then %><em><%:(empty)%></em><% end -%>
</span>
<% end end %>
<% if zempty then %><em><%:(empty)%></em><% end %>
</label>
<%- end end -%>
<%- if zempty then %><em><%:(empty)%></em><% end -%>
</span>
</li>
<% end end %>
<% if self.widget ~= "checkbox" and not self.nocreate then %>
<li style="padding:0.5em">
<input class="cbi-input-radio" data-update="click change" type="radio"<%=attr("id", cbid .. "_new") .. attr("name", cbid) .. attr("value", "-") .. ifattr(not selected, "checked", "checked")%> /> &#160;
<label<%=attr("for", cbid .. "_new")%>></label>
<div onclick="document.getElementById('<%=cbid%>_new').checked=true" class="zonebadge" style="background-color:<%=fwm.zone.get_color()%>">
<em><%:unspecified -or- create:%>&#160;</em>
<input type="text"<%=attr("name", cbid .. ".newzone") .. ifattr(not selected, "value", luci.http.formvalue(cbid .. ".newzone") or self.default)%> onfocus="document.getElementById('<%=cbid%>_new').checked=true" />
</div>
<li value="-">
<span class="zonebadge">
<em><%:create%>:</em>
<input type="password" style="display:none" />
<input class="create-item-input" type="text" />
</span>
</li>
<% end %>
</ul>
</span>
</div>
<%+cbi/valuefooter%>

View file

@ -19,7 +19,9 @@
if value then
for value in utl.imatch(value) do
checked[value] = true
for value in utl.imatch(value) do
checked[value] = true
end
end
else
local n = self.network and net:get_network(self.network)
@ -33,57 +35,51 @@
-%>
<input type="hidden" name="<%=cbeid%>" value="1" />
<ul style="margin:0; list-style-type:none">
<% for _, iface in ipairs(ifaces) do
local link = iface:adminlink()
if (not self.nobridges or not iface:is_bridge()) and
(not self.noinactive or iface:is_up()) and
iface:name() ~= self.exclude
then %>
<li>
<input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%=
attr("type", self.widget or "radio") ..
attr("id", cbid .. "." .. iface:name()) ..
attr("name", cbid) .. attr("value", iface:name()) ..
ifattr(checked[iface:name()], "checked", "checked")
%> />
<%- if not self.widget or self.widget == "checkbox" or self.widget == "radio" then -%>
<label<%=attr("for", cbid .. "." .. iface:name())%>></label>
<%- end -%>
&#160;
<label<%=attr("for", cbid .. "." .. iface:name())%>>
<% if link then -%><a href="<%=link%>"><% end -%>
<img<%=attr("title", iface:get_i18n())%> style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" />
<% if link then -%></a><% end -%>
<%=pcdata(iface:get_i18n())%>
<% local ns = iface:get_networks(); if #ns > 0 then %>(
<%- local i, n; for i, n in ipairs(ns) do -%>
<%-= (i>1) and ', ' -%>
<a href="<%=n:adminlink()%>"><%=n:name()%></a>
<%- end -%>
)<% end %>
</label>
</li>
<% end end %>
<% if not self.nocreate then %>
<li>
<input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%=
attr("type", self.widget or "radio") ..
attr("id", cbid .. "_custom") ..
attr("name", cbid) ..
attr("value", " ")
%> />
<%- if not self.widget or self.widget == "checkbox" or self.widget == "radio" then -%>
<label<%=attr("for", cbid .. "_custom")%>></label>
<%- end -%>
&#160;
<label<%=attr("for", cbid .. "_custom")%>>
<img title="<%:Custom Interface%>" style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/ethernet_disabled.png" />
<%:Custom Interface%>:
</label>
<input type="text" style="width:50px" onfocus="document.getElementById('<%=cbid%>_custom').checked=true" onblur="var x=document.getElementById('<%=cbid%>_custom'); x.value=this.value; x.checked=true" />
</li>
<% end %>
</ul>
<div class="cbi-dropdown" display-items="5" placeholder="<%:-- please select -- %>"<%=
attr("name", cbid) ..
ifattr(self.widget == "checkbox", "multiple", "multiple") ..
ifattr(self.widget == "checkbox", "optional", "optional")
%>>
<script type="item-template"><!--
<li value="{{value}}">
<img title="<%:Custom Interface%>: &quot;{{value}}&quot;" src="<%=resource%>/icons/ethernet_disabled.png" />
<span class="hide-open">{{value}}</span>
<span class="hide-close"><%:Custom Interface%>: "{{value}}"</span>
</li>
--></script>
<ul>
<% for _, iface in ipairs(ifaces) do
if (not self.nobridges or not iface:is_bridge()) and
(not self.noinactive or iface:is_up()) and
iface:name() ~= self.exclude
then %>
<li<%=
attr("value", iface:name()) ..
ifattr(checked[iface:name()], "selected", "selected")
%>>
<img<%=attr("title", iface:get_i18n())%> src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" />
<span class="hide-open"><%=pcdata(iface:name())%></span>
<span class="hide-close">
<%=pcdata(iface:get_i18n())%>
<% local ns = iface:get_networks(); if #ns > 0 then %>(
<%- local i, n; for i, n in ipairs(ns) do -%>
<%-= (i>1) and ', ' -%>
<a href="<%=n:adminlink()%>"><%=n:name()%></a>
<%- end -%>
)<% end %>
</span>
</li>
<% end end %>
<% if not self.nocreate then %>
<li value="">
<img title="<%:Custom Interface%>" src="<%=resource%>/icons/ethernet_disabled.png" />
<span><%:Custom Interface%>:</span>
<input type="password" style="display:none" />
<input class="create-item-input" type="text" />
</li>
<% end %>
</ul>
</div>
<%+cbi/valuefooter%>

View file

@ -20,66 +20,62 @@
end
-%>
<ul style="margin:0; list-style-type:none; text-align:left">
<% for _, net in ipairs(networks) do
if (net:name() ~= "loopback") and
(net:name() ~= self.exclude) and
(not self.novirtual or not net:is_virtual())
then %>
<li style="padding:0.25em 0">
<input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%=
attr("type", self.widget or "radio") ..
attr("id", cbid .. "." .. net:name()) ..
attr("name", cbid) .. attr("value", net:name()) ..
ifattr(checked[net:name()], "checked", "checked")
%> /> &#160;
<label<%=attr("for", cbid .. "." .. net:name())%>>
<div class="cbi-dropdown" display-items="5" placeholder="<%:-- please select -- %>"<%=
attr("name", cbid) ..
ifattr(self.widget == "checkbox", "multiple", "multiple") ..
ifattr(self.widget == "checkbox", "optional", "optional")
%>>
<script type="item-template"><!--
<li value="{{value}}">
<span class="ifacebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">
{{value}}: <em>(<%:create%>)</em>
</span>
</li>
--></script>
<ul>
<% if self.widget ~= "checkbox" then %>
<li value=""<%= ifattr(not value, "selected", "selected") %>>
<em><%:unspecified%></em>
</li>
<% end %>
<% for _, net in ipairs(networks) do
if (net:name() ~= "loopback") and
(net:name() ~= self.exclude) and
(not self.novirtual or not net:is_virtual())
then %>
<li<%= attr("value", net:name()) .. ifattr(checked[net:name()], "selected", "selected") %>>
<span class="ifacebadge"><%=net:name()%>:
<%
local empty = true
for _, iface in ipairs(net:is_bridge() and net:get_interfaces() or { net:get_interface() }) do
if not iface:is_bridge() then
empty = false
%>
-%>
<img<%=attr("title", iface:get_i18n())%> style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" />
<% end end %>
<% if empty then %><em><%:(no interfaces attached)%></em><% end %>
<%- end end %>
<% if empty then %>
<em class="hide-close"><%:(no interfaces attached)%></em>
<em class="hide-open">-</em>
<% end %>
</span>
</label>
</li>
<% end end %>
</li>
<% end end %>
<% if not self.nocreate then %>
<li style="padding:0.25em 0">
<input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "_new") .. attr("name", cbid) .. attr("value", "-") .. ifattr(not value and self.widget ~= "checkbox", "checked", "checked")%> /> &#160;
<%- if not self.widget or self.widget == "checkbox" or self.widget == "radio" then -%>
<label<%=attr("for", cbid .. "_new")%>></label>
<%- end -%>
<div style="padding:0.5em; display:inline">
<label<%=attr("for", cbid .. "_new")%>><em>
<% if not self.nocreate then %>
<li value="-"<%= ifattr(not value and self.widget ~= "checkbox", "selected", "selected") %>>
<em>
<%- if self.widget == "checkbox" then -%>
<%:create:%>
<%- else -%>
<%:unspecified -or- create:%>
<%- end -%>&#160;</em></label>
<%- end -%>
</em>
<input style="display:none" type="password" />
<input style="width:6em" type="text"<%=attr("name", cbid .. ".newnet")%> onfocus="document.getElementById('<%=cbid%>_new').checked=true" />
</div>
</li>
<% elseif self.widget ~= "checkbox" and self.unspecified then %>
<li style="padding:0.25em 0">
<input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%=
attr("type", self.widget or "radio") ..
attr("id", cbid .. "_uns") ..
attr("name", cbid) ..
attr("value", "") ..
ifattr(not value or #value == 0, "checked", "checked")
%> /> &#160;
<div style="padding:0.5em; display:inline">
<label<%=attr("for", cbid .. "_uns")%>><em><%:unspecified%></em></label>
</div>
</li>
<% end %>
</ul>
<input class="create-item-input" type="text" />
</li>
<% end %>
</ul>
</div>
<%+cbi/valuefooter%>

View file

@ -351,7 +351,6 @@ if has_firewall then
fwzone.template = "cbi/firewall_zonelist"
fwzone.network = arg[1]
fwzone.rmempty = false
function fwzone.cfgvalue(self, section)
self.iface = section
@ -360,22 +359,16 @@ if has_firewall then
end
function fwzone.write(self, section, value)
local zone = fw:get_zone(value)
if not zone and value == '-' then
value = m:formvalue(self:cbid(section) .. ".newzone")
if value and #value > 0 then
zone = fw:add_zone(value)
else
fw:del_network(section)
end
end
local zone = fw:get_zone(value) or fw:add_zone(value)
if zone then
fw:del_network(section)
zone:add_network(section)
end
end
function fwzone.remove(self, section)
fw:del_network(section)
end
end

View file

@ -390,22 +390,16 @@ network.novirtual = true
function network.write(self, section, value)
local i = nw:get_interface(section)
if i then
if value == '-' then
value = m:formvalue(self:cbid(section) .. ".newnet")
if value and #value > 0 then
local n = nw:add_network(value, {proto="none"})
if n then n:add_interface(i) end
else
local n = i:get_network()
if n then n:del_interface(i) end
end
else
local v
for _, v in ipairs(i:get_networks()) do
v:del_interface(i)
end
for v in ut.imatch(value) do
local n = nw:get_network(v)
local _, net, old, new = nil, nil, {}, {}
for _, net in ipairs(i:get_networks()) do
old[net:name()] = true
end
for net in ut.imatch(value) do
new[net] = true
if not old[net] then
local n = nw:get_network(net) or nw:add_network(net, { proto = "none" })
if n then
if not n:is_empty() then
n:set("type", "bridge")
@ -414,6 +408,15 @@ function network.write(self, section, value)
end
end
end
for net, _ in pairs(old) do
if not new[net] then
local n = nw:get_network(net)
if n then
n:del_interface(i)
end
end
end
end
end

View file

@ -94,14 +94,9 @@ function newnet.parse(self, section)
local net, zone
if has_firewall then
local zval = fwzone:formvalue(section)
zone = fw:get_zone(zval)
if not zone and zval == '-' then
zval = m:formvalue(fwzone:cbid(section) .. ".newzone")
if zval and #zval > 0 then
zone = fw:add_zone(zval)
end
local value = fwzone:formvalue(section)
if value and #value > 0 then
zone = fw:get_zone(value) or fw:add_zone(value)
end
end