luci-app-xinetd: add new package
[project/luci.git] / applications / luci-app-xinetd / htdocs / luci-static / resources / view / xinetd / xinetd.js
1 'use strict';
2 'require uci';
3 'require ui';
4 'require form';
5 'require view';
6 'require fs';
7 'require tools.widgets as widgets';
8
9 function validateEmpty(section, value) {
10 if (value) {
11 return true;
12 }
13 else {
14 return _('Expecting: non-empty value');
15 }
16 }
17
18 return view.extend({
19 render: function() {
20 var m, s, o;
21
22 m = new form.Map('xinetd', _('Xinetd Settings'), _('Here you can configure Xinetd services'));
23
24 s = m.section(form.GridSection, 'service');
25 s.modaltitle = _('Service definitions to be used by Xinetd');
26 s.tabbed = true;
27 s.addremove = true;
28 s.addbtntitle = _('Add new service entry');
29
30 // The following dummy values are used to show the table overview without the hint texts
31 o = s.option(form.DummyValue, 'port', _('Port'));
32 o.modalonly = false;
33
34 o = s.option(form.DummyValue, 'socket_type', _('Socket type'));
35 o.modalonly = false;
36
37 o = s.option(form.DummyValue, 'protocol', _('Protocol'));
38 o.modalonly = false;
39
40 o = s.option(form.DummyValue, 'server', _('Server'));
41 o.modalonly = false;
42
43 o = s.option(form.DummyValue, 'disable', _('Enabled'));
44 o.cfgvalue = function(section) {
45 return (uci.get('xinetd', section, 'disable') == "no") ? _("yes") : _("no");
46 };
47 o.modalonly = false;
48
49 s.tab('basic', _('Basic Settings'));
50 s.tab('advanced', _('Advanced Settings'));
51
52 // Now here follow the "real" values to be set in the modal (with the hint texts)
53
54 // Basic settings
55 o = s.taboption('basic', form.Flag, 'disable', _('Enabled'), _('Enable or Disable this service'));
56 o.enabled = 'no';
57 o.disabled = 'yes';
58 o.default = o.enabled;
59 o.rmempty = false;
60 o.modalonly = true;
61
62 o = s.taboption('basic', form.ListValue, 'type', _('Type'), _('Type of service'));
63 o.default = 'UNLISTED';
64 // FIXME for now we will only support unlisted services, maybe later we could use the (very long) list from /etc/services if needed
65 // o.value('INTERNAL', _('INTERNAL'));
66 o.value('UNLISTED', _('UNLISTED'));
67 o.rmempty = false;
68 o.modalonly = true;
69
70 o = s.taboption('basic', form.Value, 'port', _('Port'), _('The port used for this service, valid range: 0 - 65535'));
71 o.datatype = 'port';
72 o.depends('type', 'UNLISTED');
73 o.rmempty = false;
74 o.modalonly = true;
75 o.validate = function(section_id, value) {
76 var sections = uci.sections('xinetd', 'service');
77
78 for (var i = 0; i < sections.length; i++) {
79 if (uci.get('xinetd', sections[i]['.name'], 'port') == value && section_id != sections[i]['.name'])
80 return _('Port already in use by service "%s"'.format(sections[i]['.name']));
81 }
82
83 return true;
84 };
85
86 o = s.taboption('basic', form.ListValue, 'wait', _('Threading behaviour'), _('Selection of the threading for this service'));
87 o.default = 'no';
88 o.value('yes', _('Single-Threaded Service'));
89 o.value('no', _('Multi-Threaded Service'));
90 o.rmempty = false;
91 o.modalonly = true;
92
93 o = s.taboption('basic', form.ListValue, 'socket_type', _('Socket type'), _('The type of the socket used for this service'));
94 o.default = 'stream';
95 o.value('stream', _('stream-based service'));
96 o.value('dgram', _('datagram-based service'));
97 o.value('raw', _('direct access to IP service'));
98 o.value('seqpacket', _('sequential datagram transmission service'));
99 o.rmempty = false;
100 o.modalonly = true;
101
102 o = s.taboption('basic', form.ListValue, 'protocol', _('Protocol'), _('The protocol to be used for this service'));
103 o.default = 'tcp';
104 o.value('tcp', _('TCP'));
105 o.value('udp', _('UDP'));
106 o.rmempty = false;
107 o.modalonly = true;
108
109 o = s.taboption('basic', widgets.UserSelect, 'user', _('User (UID)'), _('User ID for the server process for this service'));
110 o.rmempty = false;
111 o.modalonly = true;
112
113 o = s.taboption('basic', form.Value, 'server', _('Server'), _('Complete path to the executable server file'));
114 o.datatype = 'string';
115 o.rmempty = false;
116 o.modalonly = true;
117 o.validate = validateEmpty;
118 o.write = function(section, value) {
119 return fs.stat(value).then(function(res) {
120 if (res.type == "file") {
121 uci.set('xinetd', section, 'server', value);
122 return;
123 } else {
124 ui.addNotification(null, E('p', _('Service "%s": Invalid server file "%s"').format(section, value)), 'danger');
125 }
126 }).catch(function(err) {
127 ui.addNotification(null, E('p', _('Service "%s": No access to server file "%s" (%s)').format(section, value, err.message)), 'danger');
128 return;
129 });
130 };
131
132 o = s.taboption('basic', form.Value, 'server_args', _('Server arguments'), _('Additional arguments passed to the server. There is no validation of this input.'));
133 o.datatype = 'string';
134 o.modalonly = true;
135
136 // Advanced settings
137 o = s.taboption('advanced', form.DynamicList, 'only_from', _('Allowed hosts'), _('List of allowed hosts to access this service'));
138 o.datatype = 'host';
139 o.cast = 'string';
140 o.modalonly = true;
141
142 o = s.taboption('advanced', form.DynamicList, 'no_access', _('Forbidden hosts'), _('List of forbidden hosts to access this service'));
143 o.datatype = 'host';
144 o.cast = 'string';
145 o.modalonly = true;
146
147 o = s.taboption('advanced', form.DynamicList, 'access_times', _('Access times'), _('Time intervals within service is available (Format hh:mm-hh:mm)'));
148 o.datatype = 'string';
149 o.modalonly = true;
150 o.validate = function(section_id, value) {
151 if (value.length == 0 || /^([01]\d|2[0-3]):[0-5]\d-([01]\d|2[0-3]):[0-5]\d$/.test(value) == true)
152 return true;
153
154 return _('Expected \'hh:mm-hh:mm\'');
155
156 };
157
158 o = s.taboption('advanced', form.Value, 'cps', _('Connection limit'), _('Takes two arguments: [Number of connections per second] [Number of seconds to reenable service]'));
159 o.datatype = 'string';
160 o.placeholder = '50 10';
161 o.modalonly = true;
162 o.validate = function(section_id, value) {
163 if (value.length == 0 || /^([0-9]+\s+[0-9]+$)/.test(value) == true)
164 return true;
165
166 return _('Expected \'[Number] [Number]\'');
167
168 };
169
170 o = s.taboption('advanced', form.Value, 'instances', _('Number of instances'), _('Number of simultaneously running servers for this service. Argument is any number or the keyword \'UNLIMITED\''));
171 o.datatype = 'or("UNLIMITED", uinteger)';
172 o.value('UNLIMITED', 'UNLIMITED');
173 o.modalonly = true;
174
175 o = s.taboption('advanced', form.MultiValue, 'log_on_success', _('Log on success'), _('Informations that should be logged for this service in case of successful connection'));
176 o.value('PID', _('Server PID'));
177 o.value('HOST', _('Remote host address '));
178 o.value('USERID', _('User ID of the remote user'));
179 o.value('EXIT', _('Server exited along with the exit status'));
180 o.value('DURATION', _('Duration of a service session'));
181 o.value('TRAFFIC', _('Total bytes in and out for a redirected service'));
182 o.modalonly = true;
183
184 o = s.taboption('advanced', form.MultiValue, 'log_on_failure', _('Log on failure'), _('Informations that should be logged for this service in case of a failed connection'));
185 o.value('HOST', _('Remote host address '));
186 o.value('USERID', _('User ID of the remote user'));
187 o.value('ATTEMPT', _('Failed attempts'));
188 o.modalonly = true;
189
190 return m.render();
191 }
192 });