feat: add LDAP authentication settings and toggle
Add an admin-only LDAP configuration UI with an enable toggle and full sign-in integration. Backend: - ldapSettings model + migration (single-row config) - GET/PUT/test routes under /ldap (admin-gated; bind password masked) - shared ldapClient with RFC 4515 filter escaping and empty-password guard - signin tries local auth first, then LDAP when enabled (find-or-create local user) so the bootstrap admin is never locked out Frontend: - LDAP settings page (Switch + form + test connection) under /admin/ldap - AdminNav tabs between user management and LDAP - ldapControl util, types, and Ldap i18n namespace for all 6 locales Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
14
backend/routes/ldap/ldapClient.test.js
Normal file
14
backend/routes/ldap/ldapClient.test.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildFilter, escapeFilterValue } from './ldapClient.js';
|
||||
|
||||
describe('LDAP filter building', () => {
|
||||
it('substitutes {{username}} into the filter template', () => {
|
||||
expect(buildFilter('(mail={{username}})', 'alice@example.com')).toBe('(mail=alice@example.com)');
|
||||
});
|
||||
|
||||
it('escapes RFC 4515 special characters to prevent filter injection', () => {
|
||||
// An attacker-supplied "*" or parentheses must not alter the filter shape.
|
||||
expect(escapeFilterValue('*)(uid=*')).toBe('\\2a\\29\\28uid=\\2a');
|
||||
expect(buildFilter('(uid={{username}})', 'a*b')).toBe('(uid=a\\2ab)');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user