Files
pp-tcms/backend/routes/ldap/edit.js
LittleYellow 1c977f9266 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>
2026-06-26 07:20:08 +08:00

49 lines
1.4 KiB
JavaScript

import express from 'express';
import { DataTypes } from 'sequelize';
import defineLdapSetting from '../../models/ldapSettings.js';
import authMiddleware from '../../middleware/auth.js';
import { getLdapSettings } from './ldapClient.js';
import { serialize } from './index.js';
const router = express.Router();
const editableFields = [
'enabled',
'url',
'bindDn',
'searchBase',
'searchFilter',
'emailAttribute',
'usernameAttribute',
];
export default function (sequelize) {
const { verifySignedIn, verifyAdmin } = authMiddleware(sequelize);
const LdapSetting = defineLdapSetting(sequelize, DataTypes);
router.put('/', verifySignedIn, verifyAdmin, async (req, res) => {
try {
const settings = await getLdapSettings(LdapSetting);
const updates = {};
for (const field of editableFields) {
if (req.body[field] !== undefined) {
updates[field] = req.body[field];
}
}
// Only overwrite the bind password when a non-empty value is supplied,
// so the masked GET value can be saved back without wiping it.
if (req.body.bindCredentials) {
updates.bindCredentials = req.body.bindCredentials;
}
await settings.update(updates);
res.json(serialize(settings));
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
});
return router;
}