✨ Sync 2026-07-04 23:49:55

This commit is contained in:
github-actions[bot] committed 2026-07-04 23:49:55 +08:00
1 parent 6b08744472
commit d8d6bd52be
10 files changed
+101 -35

No files matched your search

@@ -105,19 +105,29 @@ function graphQL(endpoint, query, variables, token) {
});
}
function requestDaedCredentials() {
function requestDaedCredentials(mode) {
const init = (mode === 'init');
return new Promise(function(resolve, reject) {
const username = E('input', { 'class': 'cbi-input-text', 'autocomplete': 'username', 'placeholder': _('Username') });
const password = E('input', { 'class': 'cbi-input-password', 'type': 'password', 'autocomplete': 'current-password', 'placeholder': _('Password') });
const password = E('input', { 'class': 'cbi-input-password', 'type': 'password', 'autocomplete': init ? 'new-password' : 'current-password', 'placeholder': _('Password') });
if (init) {
// prefill from the config-page account so the daed admin created here
// matches what cron subscription updates use.
username.value = uci.get('daed', 'config', 'dashboard_username') || '';
password.value = uci.get('daed', 'config', 'dashboard_password') || '';
}
const cancel = E('button', { 'class': 'btn cbi-button' }, _('Cancel'));
const login = E('button', { 'class': 'btn cbi-button cbi-button-positive' }, _('Sign in and import'));
const submit = E('button', { 'class': 'btn cbi-button cbi-button-positive' },
init ? _('Initialize and import') : _('Sign in and import'));
cancel.addEventListener('click', function() {
password.value = '';
ui.hideModal();
reject(new Error(_('Import cancelled')));
reject(new Error(init
? _('daed is not initialized yet. Open the daed web panel (port 2023) to create an admin account, then import again.')
: _('Import cancelled')));
});
login.addEventListener('click', function() {
submit.addEventListener('click', function() {
if (!username.value || !password.value)
return;
const result = { username: username.value, password: password.value };
@@ -126,11 +136,15 @@ function requestDaedCredentials() {
resolve(result);
});
ui.showModal(_('Sign in to daed'), [ E('div', { 'class': 'dd-daed-login' }, [
E('p', {}, _('The password is not saved. Sign-in is remembered in this browser for up to 30 days.')),
const intro = init
? _('daed has not been initialized yet. The account below will be created as the daed admin (password needs at least 6 characters with both letters and numbers), then used to import.')
: _('The password is not saved. Sign-in is remembered in this browser for up to 30 days.');
ui.showModal(init ? _('Initialize daed') : _('Sign in to daed'), [ E('div', { 'class': 'dd-daed-login' }, [
E('p', {}, intro),
E('div', { 'class': 'cbi-value' }, [ E('label', { 'class': 'cbi-value-title' }, _('Username')), E('div', { 'class': 'cbi-value-field' }, username) ]),
E('div', { 'class': 'cbi-value' }, [ E('label', { 'class': 'cbi-value-title' }, _('Password')), E('div', { 'class': 'cbi-value-field' }, password) ]),
E('div', { 'class': 'right dd-daed-login-actions' }, [ cancel, ' ', login ])
E('div', { 'class': 'right dd-daed-login-actions' }, [ cancel, ' ', submit ])
]) ]);
username.focus();
});
@@ -141,19 +155,28 @@ function requestDaedToken(endpoint, forceLogin) {
if (cached)
return Promise.resolve({ token: cached, cached: true });
let credentials;
return requestDaedCredentials().then(function(value) {
credentials = value;
return graphQL(endpoint,
'query Login($username:String!,$password:String!){token(username:$username,password:$password)}',
credentials);
}).then(function(login) {
daedSession.save(window.localStorage, login.token);
return { token: login.token, cached: false };
}).finally(function() {
if (credentials)
credentials.password = '';
credentials = null;
// numberUsers is unauthenticated; 0 means the daed panel was never
// initialized, so log-in can never succeed — bootstrap it with createUser.
return graphQL(endpoint, 'query Init{numberUsers}', {}).then(function(state) {
const needInit = !state || state.numberUsers === 0;
let credentials;
return requestDaedCredentials(needInit ? 'init' : 'login').then(function(value) {
credentials = value;
if (needInit)
return graphQL(endpoint,
'mutation Init($username:String!,$password:String!){createUser(username:$username,password:$password)}',
credentials).then(function(r) { return r.createUser; });
return graphQL(endpoint,
'query Login($username:String!,$password:String!){token(username:$username,password:$password)}',
credentials).then(function(r) { return r.token; });
}).then(function(token) {
daedSession.save(window.localStorage, token);
return { token: token, cached: false };
}).finally(function() {
if (credentials)
credentials.password = '';
credentials = null;
});
});
}
@@ -21,7 +21,7 @@ function renderDaedSettings() {
o.rmempty = false;
o = s.option(form.Value, 'dashboard_username', _('daed Username'),
_('Used by LuCI to update daed subscriptions through GraphQL. It does not change the daed Web login account.'));
_('Used by LuCI to access daed (subscription updates and import). If daed is not initialized yet, this account is used to create the daed admin.'));
o.placeholder = 'admin';
o.rmempty = false;
@@ -31,6 +31,7 @@ function currentPreset(gi, gs) {
const HEALTH_PATHS = {
btf: '/sys/kernel/btf/vmlinux',
btfDetached: '/usr/lib/debug/boot/vmlinux',
netns: '/run/netns/daens'
};
@@ -270,6 +271,7 @@ return view.extend({
probeFile(DATA_PATHS.geoip),
probeFile(DATA_PATHS.geosite),
probeFile(HEALTH_PATHS.btf),
probeFile(HEALTH_PATHS.btfDetached),
backend.detectRunning(),
backend.serviceStatus(ctx.name)
];
@@ -283,8 +285,8 @@ return view.extend({
probes.push(probeFile(HEALTH_PATHS.netns));
return Promise.all(probes).then(function(r) {
const geoip = r[0], geosite = r[1], btf = r[2], running = r[3], service = r[4];
const pkgOffset = 5;
const geoip = r[0], geosite = r[1], btf = r[2], btfDetached = r[3], running = r[4], service = r[5];
const pkgOffset = 6;
const coreInfo = {};
corePkgs.forEach(function(pkg, i) {
coreInfo[pkg] = r[pkgOffset + i];
@@ -364,6 +366,8 @@ return view.extend({
if (btf.exists)
healthBody.appendChild(mkRow('✓', 'dd-up-ok', _('Kernel BTF'), HEALTH_PATHS.btf + ' · ' + fmtBytes(btf.size)));
else if (btfDetached.exists)
healthBody.appendChild(mkRow('✓', 'dd-up-ok', _('Kernel BTF'), HEALTH_PATHS.btfDetached + ' · ' + fmtBytes(btfDetached.size)));
else
healthBody.appendChild(mkRow('✗', 'dd-up-err', _('Kernel BTF'), _('not available — eBPF needs CONFIG_DEBUG_INFO_BTF or vmlinux-btf')));