luci-app-pbr: bugfixes
[project/luci.git] / applications / luci-app-pbr / htdocs / luci-static / resources / view / pbr / overview.js
1 // Copyright 2022 Stan Grishin <stangri@melmac.ca>
2 // This code wouldn't have been possible without help from [@vsviridov](https://github.com/vsviridov)
3
4 'use strict';
5 'require form';
6 'require rpc';
7 'require uci';
8 'require view';
9 'require pbr.status as pbr';
10
11 var pkg = {
12 get Name() { return 'pbr'; },
13 get URL() { return 'https://docs.openwrt.melmac.net/' + pkg.Name + '/'; }
14 };
15
16 return view.extend({
17 load: function () {
18 return Promise.all([
19 uci.load(pkg.Name)
20 ]);
21 },
22
23 render: function () {
24 return Promise.all([
25 L.resolveDefault(pbr.getInterfaces(), {}),
26 L.resolveDefault(pbr.getPlatformSupport(), {}),
27 ]).then(function (data) {
28 var arrInterfaces;
29 var replyPlatform;
30 var status, m, s, o;
31
32 if (data[0] && data[0][pkg.Name] && data[0][pkg.Name].interfaces) {
33 arrInterfaces = data[0][pkg.Name].interfaces;
34 }
35 else {
36 arrInterfaces = ["wan"];
37 }
38
39 if (data[1] && data[1][pkg.Name]) {
40 replyPlatform = data[1][pkg.Name];
41 }
42 else {
43 replyPlatform = {
44 ipset_installed: null,
45 nft_installed: null,
46 adguardhome_installed: null,
47 dnsmasq_installed: null,
48 unbound_installed: null,
49 adguardhome_ipset_support: null,
50 dnsmasq_ipset_support: null,
51 dnsmasq_nftset_support: null,
52 };
53 }
54
55 status = new pbr.status();
56 m = new form.Map(pkg.Name, _("Policy Based Routing - Configuration"));
57
58 s = m.section(form.NamedSection, 'config', pkg.Name);
59 s.tab("tab_basic", _("Basic Configuration"));
60 s.tab("tab_advanced", _("Advanced Configuration"),
61 _("%sWARNING:%s Please make sure to check the %sREADME%s before changing anything in this section! " +
62 "Change any of the settings below with extreme caution!%s").format(
63 "<br/>&#160;&#160;&#160;&#160;<b>", "</b>",
64 "<a href=\"" + pkg.URL + "#service-configuration-settings \" target=\"_blank\">", "</a>", "<br/><br/>"));
65 s.tab("tab_webui", _("Web UI Configuration"))
66
67 o = s.taboption("tab_basic", form.ListValue, "verbosity", _("Output verbosity"),
68 _("Controls both system log and console output verbosity."));
69 o.value("0", _("Suppress/No output"));
70 o.value("1", _("Condensed output"));
71 o.value("2", _("Verbose output"));
72 o.default = "2";
73
74 o = s.taboption("tab_basic", form.ListValue, "strict_enforcement", _("Strict enforcement"),
75 _("See the %sREADME%s for details.").format(
76 "<a href=\"" + pkg.URL + "#strict-enforcement\" target=\"_blank\">", "</a>"));
77 o.value("0", _("Do not enforce policies when their gateway is down"));
78 o.value("1", _("Strictly enforce policies when their gateway is down"));
79 o.default = "1";
80
81 var text = "";
82 if (replyPlatform.adguardhome_ipset_support === null) {
83 text += _("The %s support is unknown.").format("<i>adguardhome.ipset</i>") + "<br />"
84 }
85 else if (!(replyPlatform.adguardhome_ipset_support)) {
86 text += _("The %s is not supported on this system.").format("<i>adguardhome.ipset</i>") + "<br />"
87 }
88 if (replyPlatform.dnsmasq_ipset_support === null) {
89 text += _("The %s support is unknown.").format("<i>dnsmasq.ipset</i>") + "<br />"
90 }
91 else if (!(replyPlatform.dnsmasq_ipset_support)) {
92 text += _("The %s is not supported on this system.").format("<i>dnsmasq.ipset</i>") + "<br />"
93 }
94 if (replyPlatform.dnsmasq_nftset_support === null) {
95 text += _("The %s support is unknown.").format("<i>dnsmasq.nftset</i>") + "<br />"
96 }
97 else if (!(replyPlatform.dnsmasq_nftset_support)) {
98 text += _("The %s is not supported on this system.").format("<i>dnsmasq.nftset</i>") + "<br />"
99 }
100 text += _("Please check the %sREADME%s before changing this option.").format(
101 "<a href=\"" + pkg.URL + "#use-resolvers-set-support\" target=\"_blank\">", "</a>");
102 o = s.taboption("tab_basic", form.ListValue, "resolver_set", _("Use resolver set support for domains"), text);
103 o.value("none", _("Disabled"));
104 if (replyPlatform.adguardhome_ipset_support) {
105 o.value("adguardhome.ipset", _("AdGuardHome ipset"));
106 o.default = ("adguardhome.ipset", _("AdGuardHome ipset"));
107 }
108 if (replyPlatform.dnsmasq_ipset_support) {
109 o.value("dnsmasq.ipset", _("Dnsmasq ipset"));
110 o.default = ("dnsmasq.ipset", _("Dnsmasq ipset"));
111 }
112 if (replyPlatform.dnsmasq_nftset_support) {
113 o.value("dnsmasq.nftset", _("Dnsmasq nft set"));
114 o.default = ("dnsmasq.nftset", _("Dnsmasq nft set"));
115 }
116
117 o = s.taboption("tab_basic", form.ListValue, "ipv6_enabled", _("IPv6 Support"));
118 o.value("0", _("Disabled"));
119 o.value("1", _("Enabled"));
120
121 o = s.taboption("tab_advanced", form.DynamicList, "supported_interface", _("Supported Interfaces"),
122 _("Allows to specify the list of interface names (in lower case) to be explicitly supported by the service. " +
123 "Can be useful if your OpenVPN tunnels have dev option other than tun* or tap*."));
124 o.optional = false;
125
126 o = s.taboption("tab_advanced", form.DynamicList, "ignored_interface", _("Ignored Interfaces"),
127 _("Allows to specify the list of interface names (in lower case) to be ignored by the service. " +
128 "Can be useful if running both VPN server and VPN client on the router."));
129 o.optional = false;
130
131 o = s.taboption("tab_advanced", form.ListValue, "rule_create_option", _("Rule Create option"),
132 _("Select Add for -A/add and Insert for -I/Insert."));
133 o.value("add", _("Add"));
134 o.value("insert", _("Insert"));
135 o.default = "add";
136
137 o = s.taboption("tab_advanced", form.ListValue, "icmp_interface", _("Default ICMP Interface"),
138 _("Force the ICMP protocol interface."));
139 o.value("", _("No Change"));
140 arrInterfaces.forEach(element => {
141 if (element.toLowerCase() !== "ignore") {
142 o.value(element);
143 }
144 });
145 o.rmempty = true;
146
147 o = s.taboption("tab_advanced", form.Value, "wan_tid", _("WAN Table ID"),
148 _("Starting (WAN) Table ID number for tables created by the service."));
149 o.rmempty = true;
150 o.placeholder = "201";
151 o.datatype = "and(uinteger, min(201))";
152
153 o = s.taboption("tab_advanced", form.Value, "wan_mark", _("WAN Table FW Mark"),
154 _("Starting (WAN) FW Mark for marks used by the service. High starting mark is " +
155 "used to avoid conflict with SQM/QoS. Change with caution together with") +
156 " " + _("Service FW Mask") + ".");
157 o.rmempty = true;
158 o.placeholder = "010000";
159 o.datatype = "hexstring";
160
161 o = s.taboption("tab_advanced", form.Value, "fw_mask", _("Service FW Mask"),
162 _("FW Mask used by the service. High mask is used to avoid conflict with SQM/QoS. " +
163 "Change with caution together with") + " " + _("WAN Table FW Mark") + ".");
164 o.rmempty = true;
165 o.placeholder = "ff0000";
166 o.datatype = "hexstring";
167
168 o = s.taboption("tab_webui", form.ListValue, "webui_show_ignore_target", _("Add Ignore Target"),
169 _("Adds 'ignore' to the list of interfaces for policies. See the %sREADME%s for details.").format(
170 "<a href=\"" + pkg.URL + "#ignore-target\" target=\"_blank\">", "</a>"));
171 o.value("0", _("Disabled"))
172 o.value("1", _("Enabled"))
173 o.default = "0";
174 o.optional = false;
175
176 o = s.taboption("tab_webui", form.DynamicList, "webui_supported_protocol", _("Supported Protocols"),
177 _("Display these protocols in protocol column in Web UI."));
178 o.optional = false;
179
180 s = m.section(form.GridSection, 'policy', _('Policies'),
181 _("Name, interface and at least one other field are required. Multiple local and remote " +
182 "addresses/devices/domains and ports can be space separated. Placeholders below represent just " +
183 "the format/syntax and will not be used if fields are left blank."));
184 s.rowcolors = true;
185 s.sortable = true;
186 s.anonymous = true;
187 s.addremove = true;
188
189 o = s.option(form.Flag, "enabled", _("Enabled"));
190 o.default = "1";
191 o.editable = true;
192
193 o = s.option(form.Value, "name", _("Name"));
194
195 o = s.option(form.Value, "src_addr", _("Local addresses / devices"));
196 o.datatype = "list(neg(or(cidr,host,ipmask,ipaddr,macaddr,network)))";
197 o.rmempty = true;
198 o.default = "";
199
200 o = s.option(form.Value, "src_port", _("Local ports"));
201 o.datatype = "list(neg(or(portrange,port)))";
202 o.placeholder = "0-65535";
203 o.rmempty = true;
204 o.default = "";
205
206 o = s.option(form.Value, "dest_addr", _("Remote addresses / domains"));
207 o.datatype = "list(neg(or(cidr,host,ipmask,ipaddr,macaddr,network)))";
208 o.rmempty = true;
209 o.default = "";
210
211 o = s.option(form.Value, "dest_port", _("Remote ports"));
212 o.datatype = "list(neg(or(portrange,port)))";
213 o.placeholder = "0-65535";
214 o.rmempty = true;
215 o.default = "";
216
217 o = s.option(form.ListValue, "proto", _("Protocol"));
218 var proto = L.toArray(uci.get(pkg.Name, "config", "webui_supported_protocol"));
219 if (!proto.length) {
220 proto = ["all", "tcp", "udp", "tcp udp", "icmp"]
221 }
222 proto.forEach(element => {
223 if (element === "all") {
224 o.value("", _("all"));
225 o.default = ("", _("all"));
226 }
227 else {
228 o.value(element.toLowerCase());
229 }
230 });
231 o.rmempty = true;
232
233 o = s.option(form.ListValue, "chain", _("Chain"));
234 o.value("", "prerouting");
235 o.value("forward", "forward");
236 o.value("input", "input");
237 o.value("output", "output");
238 o.value("postrouting", "postrouting");
239 o.default = ("", "prerouting");
240 o.rmempty = true;
241
242 o = s.option(form.ListValue, "interface", _("Interface"));
243 arrInterfaces.forEach(element => {
244 o.value(element);
245 });
246 o.datatype = "network";
247 o.rmempty = false;
248
249 s = m.section(form.NamedSection, 'config', pkg.Name, _("DSCP Tagging"),
250 _("Set DSCP tags (in range between 1 and 63) for specific interfaces. See the %sREADME%s for details.").format(
251 "<a href=\"" + pkg.URL + "#dscp-tag-based-policies" + "\" target=\"_blank\">", "</a>"));
252 arrInterfaces.forEach(element => {
253 if (element.toLowerCase() !== "ignore") {
254 o = s.option(form.Value, element + "_dscp", element.toUpperCase() + " " + _("DSCP Tag"));
255 o.datatype = "and(uinteger, min(1), max(63))";
256 }
257 });
258
259 s = m.section(form.GridSection, 'include', _("Custom User File Includes"),
260 _("Run the following user files after setting up but before restarting DNSMASQ. " +
261 "See the %sREADME%s for details.").format(
262 "<a href=\"" + pkg.URL + "#custom-user-files\" target=\"_blank\">", "</a>"));
263 s.sortable = true;
264 s.anonymous = true;
265 s.addremove = true;
266
267 o = s.option(form.Flag, "enabled", _("Enabled"));
268 o.optional = false;
269 o.editable = true;
270 o.rmempty = false;
271
272 o = s.option(form.Value, "path", _("Path"));
273 o.optional = false;
274 o.editable = true;
275 o.rmempty = false;
276
277 return Promise.all([status.render(), m.render()]);
278 })
279 }
280 });