mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-29 08:45:13 +08:00
🍓 Sync 2026-09-15 02:13:06
This commit is contained in:
1 parent
0e5393594c
commit
1dd96ac2bb
146 files changed
+26541
-508
No files matched your search
@@ -0,0 +1,102 @@
|
||||
/* This is free software, licensed under the Apache License, Version 2.0
|
||||
*
|
||||
* Copyright (C) 2024 Hilman Maulana <hilman0.0maulana@gmail.com>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
'require form';
|
||||
'require rpc';
|
||||
'require view';
|
||||
|
||||
const callServiceList = rpc.declare({
|
||||
object: 'service',
|
||||
method: 'list',
|
||||
params: ['name'],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
function getServiceStatus() {
|
||||
return L.resolveDefault(callServiceList('cloudflared'), {}).then(function (res) {
|
||||
var isRunning = false;
|
||||
try {
|
||||
isRunning = res['cloudflared']['instances']['cloudflared']['running'];
|
||||
} catch (ignored) {}
|
||||
return isRunning;
|
||||
});
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function () {
|
||||
return Promise.all([
|
||||
getServiceStatus()
|
||||
]);
|
||||
},
|
||||
|
||||
render: function (data) {
|
||||
let isRunning = data[0];
|
||||
let m, s, o;
|
||||
|
||||
m = new form.Map('cloudflared', _('Cloudflare Zero Trust Tunnel'),
|
||||
_('Cloudflare Zero Trust Security services help you get maximum security both from outside and within the network.') + '<br />' +
|
||||
_('Create and manage your network on the <a %s>Cloudflare Zero Trust</a> dashboard.')
|
||||
.format('href="https://one.dash.cloudflare.com" target="_blank"') + '<br />' +
|
||||
_('See <a %s>documentation</a>.')
|
||||
.format('href="https://openwrt.org/docs/guide-user/services/vpn/cloudfare_tunnel" target="_blank"')
|
||||
);
|
||||
|
||||
s = m.section(form.NamedSection, 'config', 'cloudflared');
|
||||
|
||||
o = s.option(form.DummyValue, '_status', _('Status'));
|
||||
o.rawhtml = true;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var span = '<b><span style="color:%s">%s</span></b>';
|
||||
var renderHTML = isRunning ?
|
||||
String.format(span, 'green', _('Running')) :
|
||||
String.format(span, 'red', _('Not Running'));
|
||||
return renderHTML;
|
||||
};
|
||||
|
||||
o = s.option(form.Flag, 'enabled', _('Enable'));
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.TextValue, 'token', _('Token'),
|
||||
_('The tunnel token is shown in the dashboard once you create a tunnel.')
|
||||
);
|
||||
o.optional = true;
|
||||
o.rmempty = false;
|
||||
o.monospace = true;
|
||||
|
||||
o = s.option(form.FileUpload, 'config', _('Config file path'),
|
||||
_('See <a %s>documentation</a>.')
|
||||
.format('href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/configure-tunnels/local-management/configuration-file/" target="_blank"')
|
||||
);
|
||||
o.default = '/etc/cloudflared/config.yml';
|
||||
o.root_directory = '/etc/cloudflared/';
|
||||
o.optional = true;
|
||||
|
||||
o = s.option(form.FileUpload, 'origincert', _('Certificate of Origin'),
|
||||
_('The account certificate for your zones authorizing the client to serve as an Origin for that zone') + '<br />' +
|
||||
_('Obtain a certificate <a %s>here</a>.')
|
||||
.format('href="https://dash.cloudflare.com/argotunnel" target="_blank"')
|
||||
);
|
||||
o.default = '/etc/cloudflared/cert.pem';
|
||||
o.root_directory = '/etc/cloudflared/';
|
||||
o.optional = true;
|
||||
|
||||
o = s.option(form.ListValue, 'region', _('Region'),
|
||||
_('The region to which connections are established.')
|
||||
);
|
||||
o.value('us', _('United States'));
|
||||
o.optional = true;
|
||||
|
||||
o = s.option(form.ListValue, 'loglevel', _('Logging level'));
|
||||
o.value('fatal', _('Fatal'));
|
||||
o.value('error', _('Error'));
|
||||
o.value('warn', _('Warning'));
|
||||
o.value('info', _('Info'));
|
||||
o.value('debug', _('Debug'));
|
||||
o.default = 'info';
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,125 @@
|
||||
/* This is free software, licensed under the Apache License, Version 2.0
|
||||
*
|
||||
* Copyright (C) 2024 Hilman Maulana <hilman0.0maulana@gmail.com>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require view';
|
||||
'require poll';
|
||||
|
||||
function formatLogEntry(logObj) {
|
||||
var formattedTime = new Date(logObj.time).toISOString().replace('T', ' ').split('.')[0];
|
||||
var tunnelIDMessage = logObj.tunnelID ? ', ID: ' + logObj.tunnelID : '';
|
||||
var errorMessage = logObj.error ? ', Error: ' + logObj.error : '';
|
||||
var ipMessage = logObj.ip ? ', IP: ' + logObj.ip : '';
|
||||
var configMessage = logObj.config ? ', Config: ' + JSON.stringify(logObj.config) : '';
|
||||
var connectionMessage = logObj.connection ? ', Connection: ' + JSON.stringify(logObj.connection) : '';
|
||||
var locationMessage = logObj.location ? ', Location: ' + logObj.location : '';
|
||||
var protocolMessage = logObj.protocol ? ', Protocol: ' + logObj.protocol : '';
|
||||
|
||||
return '[' + formattedTime + '] [' + logObj.level + '] : ' + logObj.message + ipMessage + tunnelIDMessage + errorMessage + configMessage + connectionMessage + locationMessage + protocolMessage;
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null,
|
||||
load: function() {
|
||||
poll.add(function () {
|
||||
return fs.read('/var/log/cloudflared.log').then(function(res) {
|
||||
if (!res || res.trim() === '') {
|
||||
ui.addNotification(null, E('p', {}, _('Unable to read the interface info from /var/log/cloudflared.log.')));
|
||||
return '';
|
||||
}
|
||||
|
||||
var logs = res.trim().split('\n').map(function(entry) {
|
||||
try {
|
||||
var logObj = JSON.parse(entry);
|
||||
return logObj.time && logObj.message && logObj.level
|
||||
? formatLogEntry(logObj)
|
||||
: '';
|
||||
} catch (error) {
|
||||
console.error('Error parsing log entry:', error);
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
logs = logs.filter(function(entry) {
|
||||
return entry.trim() !== '';
|
||||
});
|
||||
|
||||
var info = logs.join('\n');
|
||||
var view = document.getElementById('syslog');
|
||||
var filterLevel = document.getElementById('filter-level').value;
|
||||
var logDirection = document.getElementById('log-direction').value;
|
||||
|
||||
if (view) {
|
||||
var filteredLogs;
|
||||
if (filterLevel !== 'all') {
|
||||
filteredLogs = logs.filter(function(entry) {
|
||||
var logLevel = entry.match(/\[.*\] \[(.*)\]/)[1].toLowerCase();
|
||||
return logLevel.includes(filterLevel.toLowerCase());
|
||||
});
|
||||
} else {
|
||||
filteredLogs = logs;
|
||||
}
|
||||
|
||||
if (logDirection === 'up') {
|
||||
filteredLogs = filteredLogs.reverse();
|
||||
}
|
||||
|
||||
info = filteredLogs.join('\n');
|
||||
view.innerHTML = info;
|
||||
}
|
||||
|
||||
return info;
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.resolve('');
|
||||
},
|
||||
render: function(info) {
|
||||
return E([], [
|
||||
E('h2', { 'class': 'section-title' }, _('Log')),
|
||||
E('div', { 'id': 'logs' }, [
|
||||
E('label', { 'for': 'filter-level', 'style': 'margin-right: 8px;' }, _('Filter Level:')),
|
||||
E('select', { 'id': 'filter-level', 'style': 'margin-right: 8px;' }, [
|
||||
E('option', { 'value': 'all', 'selected': 'selected' }, _('All')),
|
||||
E('option', { 'value': 'info' }, _('Info')),
|
||||
E('option', { 'value': 'warn' }, _('Warn')),
|
||||
E('option', { 'value': 'error' }, _('Error')),
|
||||
]),
|
||||
E('label', { 'for': 'log-direction', 'style': 'margin-right: 8px;' }, _('Log Direction:')),
|
||||
E('select', { 'id': 'log-direction', 'style': 'margin-right: 8px;' }, [
|
||||
E('option', { 'value': 'down', 'selected': 'selected' }, _('Down')),
|
||||
E('option', { 'value': 'up' }, _('Up')),
|
||||
]),
|
||||
E('button', {
|
||||
'id': 'download-log',
|
||||
'class': 'cbi-button cbi-button-save',
|
||||
'click': L.bind(this.handleDownloadLog, this),
|
||||
'style': 'margin-bottom: 8px;'
|
||||
}, _('Download Log')),
|
||||
E('textarea', {
|
||||
'id': 'syslog',
|
||||
'class': 'cbi-input-textarea',
|
||||
'style': 'height: 500px; overflow-y: scroll;',
|
||||
'readonly': 'readonly',
|
||||
'wrap': 'off',
|
||||
'rows': 1
|
||||
}, [ info ])
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
handleDownloadLog: function() {
|
||||
var logs = document.getElementById('syslog').value;
|
||||
var blob = new Blob([logs], { type: 'text/plain' });
|
||||
var link = document.createElement('a');
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.download = 'cloudflared.log';
|
||||
link.click();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
/* This is free software, licensed under the Apache License, Version 2.0
|
||||
*
|
||||
* Copyright (C) 2024 Sergey Ponomarev <stokito@gmail.com>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
'require view';
|
||||
'require fs';
|
||||
|
||||
function listTunnels() {
|
||||
let command = '/usr/bin/cloudflared';
|
||||
let commandArgs = ['tunnel', 'list', '-o', 'json'];
|
||||
return fs.exec(command, commandArgs).then(function (res) {
|
||||
if (res.code === 0) {
|
||||
return JSON.parse(res.stdout);
|
||||
} else {
|
||||
throw new Error(res.stdout + ' ' + res.stderr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null,
|
||||
|
||||
load: function () {
|
||||
return Promise.all([
|
||||
listTunnels()
|
||||
]);
|
||||
},
|
||||
|
||||
render: function (data) {
|
||||
var tunnels = data[0];
|
||||
|
||||
var tunnelRows = tunnels.map(function (tunnel, index) {
|
||||
var rowClass = index % 2 === 0 ? 'cbi-rowstyle-1' : 'cbi-rowstyle-2';
|
||||
var tunneldate = new Date(tunnel.created_at).toLocaleString();
|
||||
return E('tr', { 'class': 'tr ' + rowClass }, [
|
||||
E('td', {'class': 'td'}, tunnel.name),
|
||||
E('td', {'class': 'td'}, tunnel.id),
|
||||
E('td', {'class': 'td'}, tunneldate),
|
||||
E('td', {'class': 'td'}, tunnel.connections.length)
|
||||
]);
|
||||
});
|
||||
|
||||
var tunnelTable = [
|
||||
E('h3', _('Tunnels Information')),
|
||||
E('table', { 'class': 'table cbi-section-table' }, [
|
||||
E('tr', { 'class': 'tr table-titles' }, [
|
||||
E('th', {'class': 'th'}, _('Name')),
|
||||
E('th', {'class': 'th'}, _('ID')),
|
||||
E('th', {'class': 'th'}, _('Created At')),
|
||||
E('th', {'class': 'th'}, _('Connections'))
|
||||
]),
|
||||
E(tunnelRows)
|
||||
])
|
||||
];
|
||||
|
||||
var connectionsTables = tunnels.map(function (tunnel) {
|
||||
var connectionsTable;
|
||||
if (tunnel.connections.length > 0) {
|
||||
var connectionRows = tunnel.connections.map(function (connection, index) {
|
||||
var rowClass = index % 2 === 0 ? 'cbi-rowstyle-1' : 'cbi-rowstyle-2';
|
||||
var connectiondate = new Date(connection.opened_at).toLocaleString();
|
||||
return E('tr', { 'class': 'tr ' + rowClass }, [
|
||||
E('td', {'class': 'td'}, connection.id),
|
||||
E('td', {'class': 'td'}, connection.origin_ip),
|
||||
E('td', {'class': 'td'}, connectiondate),
|
||||
E('td', {'class': 'td'}, connection.colo_name)
|
||||
]);
|
||||
});
|
||||
|
||||
connectionsTable = E('table', { 'class': 'table cbi-section-table' }, [
|
||||
E('tr', { 'class': 'tr table-titles' }, [
|
||||
E('th', {'class': 'th'}, _('Connection ID')),
|
||||
E('th', {'class': 'th'}, _('Origin IP')),
|
||||
E('th', {'class': 'th'}, _('Opened At')),
|
||||
E('th', {'class': 'th'}, _('Data Center'))
|
||||
]),
|
||||
E(connectionRows)
|
||||
]);
|
||||
} else {
|
||||
connectionsTable = E('div', {'class':'cbi-value center'}, [
|
||||
E('em', _('No connections'))
|
||||
]);
|
||||
}
|
||||
|
||||
return E('div', {'class': 'cbi-section'}, [
|
||||
E('h3', _('Connections') + ' ' + tunnel.name),
|
||||
E(connectionsTable)
|
||||
]);
|
||||
});
|
||||
|
||||
return E([], [
|
||||
E('h2', { 'class': 'section-title' }, _('Tunnels')),
|
||||
E('div', {'class': 'cbi-section'}, tunnelTable),
|
||||
E(connectionsTables)
|
||||
]);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user