d0a936cc6e179b9ab4e88cf0a0bf8af8107d379f
[openwrt-luci.git] /
1 'use strict';
2 'require view';
3 'require dom';
4 'require poll';
5 'require fs';
6 'require ui';
7
8 function formatTime(seconds, selectCount) {
9         var days = Math.floor(seconds / (60 * 60 * 24));
10         var hours = Math.floor(seconds / (60 * 60)) % 24;
11         var minutes = Math.floor(seconds / 60) % 60;
12         var seconds = Math.floor(seconds % 60);
13
14         var times = [
15                 [days, _('Day'), _('Days')],
16                 [hours, _('Hour'), _('Hours')],
17                 [minutes, _('Minute'), _('Minutes')],
18                 [seconds, _('Second'), _('Seconds')]
19         ].filter(function ([time, singular, plural]) {
20                 return time > 0;
21         });
22
23         var selectedTimes = times.slice(0, selectCount);
24         return selectedTimes.map(function ([time, singular, plural]) {
25                 var unit = time > 1 ? plural : singular;
26                 return '%d %s'.format(time, unit);
27         }).join(', ');
28 }
29
30 function buildSection(name, table) {
31         return E('div', { 'class': 'cbi-section' }, [
32                 E('h2', [name]),
33                 table
34         ]);
35 }
36
37 function buildTable(rows) {
38         return E('table', { 'class': 'table', }, rows);
39 }
40
41 function buildKeyValueTable(kvPairs) {
42         var rows = kvPairs.map(function (row) {
43                 return E('tr', { 'class': 'tr' }, [
44                         E('td', { 'class': 'td', 'width': '33%' }, E('strong', [row[0]])),
45                         E('td', { 'class': 'td' }, [row[1]])
46                 ]);
47         });
48         return buildTable(rows);
49 }
50
51 function collectErrorMessages(results) {
52         var errorMessages = results.reduce(function (messages, result) {
53                 return messages.concat(result.errors.map(function (error) {
54                         return error.message;
55                 }));
56         }, []);
57         var uniqueErrorMessages = new Set(errorMessages);
58
59         return [...uniqueErrorMessages];
60 }
61
62 return view.extend({
63         load: function () {
64                 return Promise.all([
65                         fs.exec_direct('/usr/sbin/swanmon', ['version'], 'json'),
66                         fs.exec_direct('/usr/sbin/swanmon', ['stats'], 'json'),
67                         fs.exec_direct('/usr/sbin/swanmon', ['list-sas'], 'json')
68                 ]);
69         },
70
71         pollData: function (container) {
72                 poll.add(L.bind(function () {
73                         return this.load().then(L.bind(function (results) {
74                                 dom.content(container, this.renderContent(results));
75                         }, this));
76                 }, this));
77         },
78
79         renderContent: function (results) {
80                 var node = E('div', [E('div')]);
81                 var firstNode = node.firstElementChild;
82
83                 var errorMessages = collectErrorMessages(results);
84                 if (errorMessages.length > 0) {
85                         var messageEls = errorMessages.map(function (message) {
86                                 return E('li', message);
87                         });
88
89                         firstNode.appendChild(E('h4', _('Querying strongSwan failed')));
90                         firstNode.appendChild(E('ul', messageEls));
91
92                         return node;
93                 }
94
95                 var [version, stats, sas] = results.map(function (r) {
96                         return r.data;
97                 });
98
99                 var uptimeSeconds = (new Date() - new Date(stats.uptime.since)) / 1000;
100                 var statsSection = buildSection(_('Stats'), buildKeyValueTable([
101                         [_('Version'), version.version],
102                         [_('Uptime'), formatTime(uptimeSeconds, 2)],
103                         [_('Daemon'), version.daemon],
104                         [_('Active IKE_SAs'), stats.ikesas.total],
105                         [_('Half-Open IKE_SAs'), stats.ikesas['half-open']]
106                 ]));
107                 firstNode.appendChild(statsSection);
108
109                 var tableRows = sas.map(function (conn) {
110                         var name = Object.keys(conn)[0];
111                         var data = conn[name];
112                         var childSas = [];
113
114                         Object.entries(data['child-sas']).forEach(function ([name, data]) {
115                                 var table = buildKeyValueTable([
116                                         [_('State'), data.state],
117                                         [_('Mode'), data.mode],
118                                         [_('Protocol'), data.protocol],
119                                         [_('Local Traffic Selectors'), data['local-ts'].join(', ')],
120                                         [_('Remote Traffic Selectors'), data['remote-ts'].join(', ')],
121                                         [_('Encryption Algorithm'), data['encr-alg']],
122                                         [_('Encryption Keysize'), data['encr-keysize']],
123                                         [_('Bytes in'), data['bytes-in']],
124                                         [_('Bytes out'), data['bytes-out']],
125                                         [_('Life Time'), formatTime(data['life-time'], 2)],
126                                         [_('Install Time'), formatTime(data['install-time'], 2)],
127                                         [_('Rekey in'), formatTime(data['rekey-time'], 2)],
128                                         [_('SPI in'), data['spi-in']],
129                                         [_('SPI out'), data['spi-out']]
130                                 ]);
131                                 childSas.push(E('div', { 'class': 'cbi-section' }, [
132                                         E('h4', { 'style': 'margin-top: 0; padding-top: 0;' }, [name]),
133                                         table
134                                 ]));
135                         });
136                         childSas.push(E('button', {
137                                 'class': 'btn cbi-button cbi-button-apply',
138                                 'click': ui.hideModal
139                         }, _('Close')));
140
141                         return E('tr', { 'class': 'tr' }, [
142                                 E('td', { 'class': 'td' }, [name]),
143                                 E('td', { 'class': 'td' }, [data.state]),
144                                 E('td', { 'class': 'td' }, [data['remote-host']]),
145                                 E('td', { 'class': 'td' }, [data.version]),
146                                 E('td', { 'class': 'td' }, [formatTime(data.established, 2)]),
147                                 E('td', { 'class': 'td' }, [formatTime(data['reauth-time'], 2)]),
148                                 E('td', { 'class': 'td' }, [E('button', {
149                                         'class': 'btn cbi-button cbi-button-apply',
150                                         'click': function (ev) {
151                                                 ui.showModal(_('CHILD_SAs'), childSas)
152                                         }
153                                 }, _('Show Details'))])
154                         ]);
155                 });
156                 var connSection = buildSection(_('Security Associations (SAs)'), buildTable([
157                         E('tr', { 'class': 'tr' }, [
158                                 E('th', { 'class': 'th' }, [_('Name')]),
159                                 E('th', { 'class': 'th' }, [_('State')]),
160                                 E('th', { 'class': 'th' }, [_('Remote')]),
161                                 E('th', { 'class': 'th' }, [_('IKE Version')]),
162                                 E('th', { 'class': 'th' }, [_('Established for')]),
163                                 E('th', { 'class': 'th' }, [_('Reauthentication in')]),
164                                 E('th', { 'class': 'th' }, [_('Details')])
165                         ]),
166                         ...tableRows
167                 ]));
168                 firstNode.appendChild(connSection);
169
170                 return node;
171         },
172
173         render: function (results) {
174                 var content = E([], [
175                         E('h2', [_('strongSwan Status')]),
176                         E('div')
177                 ]);
178                 var container = content.lastElementChild;
179
180                 dom.content(container, this.renderContent(results));
181                 this.pollData(container);
182
183                 return content;
184         },
185
186         handleSaveApply: null,
187         handleSave: null,
188         handleReset: null
189 });
git clone https://git.99rst.org/PROJECT