Skip to content

Commit 1760083

Browse files
luci-base: add extra auth plugin config
Revert "luci-mod-system: add extra auth plugin config" add extra auth plugin config page in luci-mod-system Signed-off-by: Han Yiming <moebest@outlook.jp>
1 parent ae8ed19 commit 1760083

File tree

5 files changed

+207
-43
lines changed

5 files changed

+207
-43
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
'use strict';
2+
'require view';
3+
'require dom';
4+
'require ui';
5+
'require uci';
6+
'require rpc';
7+
8+
var callListAuthPlugins = rpc.declare({
9+
object: 'luci',
10+
method: 'listAuthPlugins',
11+
expect: { }
12+
});
13+
14+
return view.extend({
15+
load: function() {
16+
return Promise.all([
17+
uci.load('luci'),
18+
callListAuthPlugins()
19+
]);
20+
},
21+
22+
render: function(data) {
23+
var pluginsData = data[1] || { external_auth: '0', plugins: [] };
24+
var externalAuth = pluginsData.external_auth == '1';
25+
var plugins = pluginsData.plugins || [];
26+
27+
var body = E('div', { 'class': 'cbi-map' }, [
28+
E('h2', {}, _('Authentication Settings')),
29+
E('div', { 'class': 'cbi-map-descr' },
30+
_('Configure global authentication settings and manage individual authentication plugins.'))
31+
]);
32+
33+
// Global settings section
34+
var globalSection = E('div', { 'class': 'cbi-section' }, [
35+
E('h3', {}, _('Global Settings')),
36+
E('div', { 'class': 'cbi-section-descr' },
37+
_('Enable or disable external authentication system-wide. When disabled, only password authentication is used.'))
38+
]);
39+
40+
var globalTable = E('table', { 'class': 'table cbi-section-table' });
41+
var globalRow = E('tr', { 'class': 'tr cbi-section-table-row' });
42+
43+
var globalCheckbox = E('input', {
44+
'type': 'checkbox',
45+
'id': 'external_auth',
46+
'checked': externalAuth ? '' : null
47+
});
48+
49+
globalRow.appendChild(E('td', { 'class': 'td cbi-value-field', 'style': 'width: 30px;' }, globalCheckbox));
50+
globalRow.appendChild(E('td', { 'class': 'td' }, [
51+
E('label', { 'for': 'external_auth', 'style': 'font-weight: bold;' }, _('Enable External Authentication')),
52+
E('br'),
53+
E('span', { 'class': 'cbi-value-description' },
54+
_('When enabled, authentication plugins in /usr/share/luci/auth.d/ will be loaded and used for additional verification during login.'))
55+
]));
56+
57+
globalTable.appendChild(globalRow);
58+
globalSection.appendChild(globalTable);
59+
body.appendChild(globalSection);
60+
61+
// Plugin settings section
62+
var pluginSection = E('div', { 'class': 'cbi-section' }, [
63+
E('h3', {}, _('Authentication Plugins')),
64+
E('div', { 'class': 'cbi-section-descr' },
65+
_('Enable or disable individual authentication plugins. Disabled plugins will be skipped during login.'))
66+
]);
67+
68+
if (plugins.length === 0) {
69+
pluginSection.appendChild(E('p', { 'class': 'cbi-section-note' },
70+
_('No authentication plugins found in /usr/share/luci/auth.d/')
71+
));
72+
} else {
73+
var pluginTable = E('table', { 'class': 'table cbi-section-table' }, [
74+
E('tr', { 'class': 'tr table-titles' }, [
75+
E('th', { 'class': 'th cbi-section-table-cell', 'style': 'width: 50px;' }, _('Enabled')),
76+
E('th', { 'class': 'th cbi-section-table-cell' }, _('Plugin Name')),
77+
E('th', { 'class': 'th cbi-section-table-cell' }, _('Filename'))
78+
])
79+
]);
80+
81+
for (var i = 0; i < plugins.length; i++) {
82+
var plugin = plugins[i];
83+
var pluginRow = E('tr', { 'class': 'tr cbi-section-table-row' });
84+
85+
var pluginCheckbox = E('input', {
86+
'type': 'checkbox',
87+
'id': 'plugin_' + plugin.name,
88+
'data-plugin': plugin.name,
89+
'checked': plugin.enabled ? '' : null
90+
});
91+
92+
pluginRow.appendChild(E('td', { 'class': 'td cbi-value-field', 'style': 'text-align: center;' }, pluginCheckbox));
93+
pluginRow.appendChild(E('td', { 'class': 'td' }, plugin.name));
94+
pluginRow.appendChild(E('td', { 'class': 'td' }, plugin.filename));
95+
96+
pluginTable.appendChild(pluginRow);
97+
}
98+
99+
pluginSection.appendChild(pluginTable);
100+
}
101+
102+
body.appendChild(pluginSection);
103+
104+
return body;
105+
},
106+
107+
handleSave: function() {
108+
var externalAuthCheckbox = document.getElementById('external_auth');
109+
var externalAuthValue = externalAuthCheckbox && externalAuthCheckbox.checked ? '1' : '0';
110+
111+
// Save global external_auth setting
112+
uci.set('luci', 'main', 'external_auth', externalAuthValue);
113+
114+
// Save individual plugin settings
115+
var pluginCheckboxes = document.querySelectorAll('input[data-plugin]');
116+
pluginCheckboxes.forEach(function(checkbox) {
117+
var pluginName = checkbox.getAttribute('data-plugin');
118+
var isDisabled = !checkbox.checked ? '1' : '0';
119+
120+
// Ensure sauth section exists (type: internal)
121+
if (!uci.get('luci', 'sauth')) {
122+
uci.add('luci', 'internal', 'sauth');
123+
}
124+
125+
uci.set('luci', 'sauth', pluginName + '_disabled', isDisabled);
126+
});
127+
128+
return uci.save().then(function() {
129+
return uci.apply();
130+
}).then(function() {
131+
ui.addNotification(null, E('p', _('Authentication settings have been saved.')), 'info');
132+
}).catch(function(err) {
133+
ui.addNotification(null, E('p', _('Failed to save authentication settings: ') + err.message), 'danger');
134+
});
135+
},
136+
137+
handleSaveApply: null,
138+
handleReset: null
139+
});

modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
},
1818
"ubus": {
1919
"file": [ "list" ],
20+
"luci": [ "listAuthPlugins" ],
2021
"uci": [ "changes", "get" ]
2122
},
2223
"uci": [ "system" ]

modules/luci-base/root/usr/share/rpcd/ucode/luci

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,41 @@ const methods = {
679679

680680
return { result: dev_stats };
681681
}
682+
},
683+
684+
listAuthPlugins: {
685+
call: function() {
686+
const uci = cursor();
687+
let plugins = [];
688+
let auth_plugins_dir = '/usr/share/luci/auth.d';
689+
690+
// Get global external_auth setting
691+
let external_auth = uci.get('luci', 'main', 'external_auth') || '0';
692+
693+
// List files in auth.d directory
694+
let files = glob(auth_plugins_dir + '/*.uc') || [];
695+
696+
for (let path in files) {
697+
// Extract filename without extension as plugin name
698+
let filename = replace(path, auth_plugins_dir + '/', '');
699+
let plugin_name = replace(filename, '.uc', '');
700+
701+
// Check if this plugin is disabled
702+
let is_disabled = uci.get('luci', 'sauth', plugin_name + '_disabled');
703+
let enabled = (is_disabled != '1');
704+
705+
push(plugins, {
706+
name: plugin_name,
707+
filename: filename,
708+
enabled: enabled
709+
});
710+
}
711+
712+
return {
713+
external_auth: external_auth,
714+
plugins: plugins
715+
};
716+
}
682717
}
683718
};
684719

modules/luci-mod-system/htdocs/luci-static/resources/view/system/password.js

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44
'require ui';
55
'require form';
66
'require rpc';
7-
'require uci';
87

98
var formData = {
109
password: {
1110
pw1: null,
12-
pw2: null,
13-
external_auth: null
11+
pw2: null
1412
}
1513
};
1614

@@ -22,10 +20,6 @@ var callSetPassword = rpc.declare({
2220
});
2321

2422
return view.extend({
25-
load: function() {
26-
return uci.load('luci');
27-
},
28-
2923
checkPassword: function(section_id, value) {
3024
var strength = document.querySelector('.cbi-value-description'),
3125
strongRegex = new RegExp("^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$", "g"),
@@ -49,9 +43,7 @@ return view.extend({
4943
render: function() {
5044
var m, s, o;
5145

52-
formData.password.external_auth = uci.get('luci', 'main', 'external_auth') || '0';
53-
54-
m = new form.JSONMap(formData, _('Router Password'), _('Changes the administrator password for accessing the device and configures secondary authentication.'));
46+
m = new form.JSONMap(formData, _('Router Password'), _('Changes the administrator password for accessing the device'));
5547
m.readonly = !L.hasViewPermission();
5648

5749
s = m.section(form.NamedSection, 'password', 'password');
@@ -73,47 +65,31 @@ return view.extend({
7365
return node;
7466
};
7567

76-
o = s.option(form.Flag, 'external_auth', _('Enable external auth plugins'),
77-
_('Allow third-party plugins (like 2FA) to provide additional authentication challenges.'));
78-
o.enabled = '1';
79-
o.disabled = '0';
80-
o.default = o.disabled;
81-
8268
return m.render();
8369
},
8470

8571
handleSave: function() {
8672
var map = document.querySelector('.cbi-map');
87-
var self = this;
8873

8974
return dom.callClassMethod(map, 'save').then(function() {
75+
if (formData.password.pw1 == null || formData.password.pw1.length == 0)
76+
return;
77+
78+
if (formData.password.pw1 != formData.password.pw2) {
79+
ui.addNotification(null, E('p', _('Given password confirmation did not match, password not changed!')), 'danger');
80+
return;
81+
}
82+
83+
return callSetPassword('root', formData.password.pw1).then(function(success) {
84+
if (success)
85+
ui.addNotification(null, E('p', _('The system password has been successfully changed.')), 'info');
86+
else
87+
ui.addNotification(null, E('p', _('Failed to change the system password.')), 'danger');
88+
89+
formData.password.pw1 = null;
90+
formData.password.pw2 = null;
9091

91-
uci.set('luci', 'main', 'external_auth', formData.password.external_auth);
92-
93-
return uci.save().then(function() {
94-
return uci.commit('luci');
95-
}).then(function() {
96-
if (formData.password.pw1 != null && formData.password.pw1.length > 0) {
97-
if (formData.password.pw1 != formData.password.pw2) {
98-
ui.addNotification(null, E('p', _('Given password confirmation did not match, password not changed!')), 'danger');
99-
return;
100-
}
101-
102-
return callSetPassword('root', formData.password.pw1).then(function(success) {
103-
if (success) {
104-
ui.addNotification(null, E('p', _('Password and authentication settings have been successfully changed.')), 'info');
105-
} else {
106-
ui.addNotification(null, E('p', _('Failed to change the system password.')), 'danger');
107-
}
108-
109-
formData.password.pw1 = null;
110-
formData.password.pw2 = null;
111-
dom.callClassMethod(map, 'render');
112-
});
113-
} else {
114-
ui.addNotification(null, E('p', _('Authentication settings have been successfully saved.')), 'info');
115-
dom.callClassMethod(map, 'render');
116-
}
92+
dom.callClassMethod(map, 'render');
11793
});
11894
});
11995
},

modules/luci-mod-system/root/usr/share/luci/menu.d/luci-mod-system.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@
8585
}
8686
},
8787

88+
"admin/system/admin/exauth": {
89+
"title": "Authentication",
90+
"order": 6,
91+
"action": {
92+
"type": "view",
93+
"path": "system/exauth"
94+
},
95+
"depends": {
96+
"acl": [ "luci-mod-system-config" ],
97+
"uci": { "luci": true }
98+
}
99+
},
100+
88101
"admin/system/startup": {
89102
"title": "Startup",
90103
"order": 45,

0 commit comments

Comments
 (0)