refactor: 拆分SystemManager.tsx(569→308行)提取useLdapManagement自定义Hook封装全部LDAP状态与业务逻辑
This commit is contained in:
1 parent
d234cb4b89
commit
019a9d13f3
2 files changed
+359
-284
No files matched your search
@@ -1,15 +1,15 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { CheckCircle, XCircle, Users, Shield, FileCode, Settings } from 'lucide-react';
|
||||
import { userApi, ldapApi } from '@/services/api';
|
||||
import { userApi } from '@/services/api';
|
||||
import type { Role } from '@/types';
|
||||
import { SystemUserTab } from './SystemUserTab';
|
||||
import { SystemRolesTab } from './SystemRolesTab';
|
||||
import { SystemLogsTab } from './SystemLogsTab';
|
||||
import { SystemSettingsTab, type LdapFormData } from './SystemSettingsTab';
|
||||
import { SystemSettingsTab } from './SystemSettingsTab';
|
||||
import { useLdapManagement } from './useLdapManagement';
|
||||
import type { UserFormData } from './UserFormDialog';
|
||||
|
||||
// 后端用户数据转换为前端兼容格式
|
||||
@@ -49,48 +49,11 @@ export function SystemManager() {
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [form, setForm] = useState<UserFormData>({ ...emptyForm });
|
||||
|
||||
// 批量导入弹窗
|
||||
// CSV 批量导入弹窗
|
||||
const [importDialogOpen, setImportDialogOpen] = useState<'csv' | 'ldap' | null>(null);
|
||||
const [importPreview, setImportPreview] = useState<any[]>([]);
|
||||
const [importing, setImporting] = useState(false);
|
||||
const [importResult, setImportResult] = useState<any>(null);
|
||||
|
||||
// LDAP 用户列表
|
||||
const [ldapUsers, setLdapUsers] = useState<any[]>([]);
|
||||
const [ldapSelected, setLdapSelected] = useState<Set<string>>(new Set());
|
||||
const [ldapLoading, setLdapLoading] = useState(false);
|
||||
const [ldapImportOUs, setLdapImportOUs] = useState<any[]>([]);
|
||||
const [ldapImportOUDN, setLdapImportOUDN] = useState('');
|
||||
|
||||
// LDAP 配置
|
||||
const [ldapConfig, setLdapConfig] = useState<any>(null);
|
||||
const [ldapForm, setLdapForm] = useState<LdapFormData>({
|
||||
ldap_host: '', ldap_port: 389, use_ldaps: false,
|
||||
admin_dn: '', admin_password: '', base_dn: '', search_filter: '',
|
||||
});
|
||||
const [ldapSaving, setLdapSaving] = useState(false);
|
||||
const [ldapTesting, setLdapTesting] = useState(false);
|
||||
const [ldapTestResult, setLdapTestResult] = useState<string | null>(null);
|
||||
const [ldapMgmtOpen, setLdapMgmtOpen] = useState(false);
|
||||
const [importFeedback, setImportFeedback] = useState<string | null>(null);
|
||||
const [importResultOpen, setImportResultOpen] = useState(false);
|
||||
|
||||
// LDAP 账号管理
|
||||
const [ldapOUs, setLdapOUs] = useState<any[]>([]);
|
||||
const [selectedOUDN, setSelectedOUDN] = useState('');
|
||||
const [selectedLDAPUsers, setSelectedLDAPUsers] = useState<string[]>([]);
|
||||
const [createOUOpen, setCreateOUOpen] = useState(false);
|
||||
const [createUserOpen, setCreateUserOpen] = useState(false);
|
||||
const [ouForm, setOuForm] = useState({ ou_name: '', parent_dn: '', description: '' });
|
||||
const [newUser, setNewUser] = useState({ username: '', password: '', display_name: '', email: '', ou_dn: '' });
|
||||
const [ldapUserTestOpen, setLdapUserTestOpen] = useState(false);
|
||||
const [ldapTestUser, setLdapTestUser] = useState('');
|
||||
const [ldapTestPass, setLdapTestPass] = useState('');
|
||||
const [ldapUserTesting, setLdapUserTesting] = useState(false);
|
||||
const [ldapUserTestResult, setLdapUserTestResult] = useState<any>(null);
|
||||
const [editLdapUser, setEditLdapUser] = useState<any>(null);
|
||||
const [editLdapForm, setEditLdapForm] = useState({ cn: '', mail: '', phone: '', title: '' });
|
||||
|
||||
const loadUsers = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
@@ -105,16 +68,18 @@ export function SystemManager() {
|
||||
}
|
||||
};
|
||||
|
||||
// LDAP 状态全部由 hook 管理(在 loadUsers 之后调用避免 TDZ) // Logan.Li
|
||||
const ldap = useLdapManagement(loadUsers);
|
||||
|
||||
useEffect(() => {
|
||||
loadUsers();
|
||||
loadLdapConfig();
|
||||
ldap.loadLdapConfig();
|
||||
}, []);
|
||||
|
||||
// LDAP 导入 Dialog 打开时加载 OU 和用户
|
||||
useEffect(() => {
|
||||
if (importDialogOpen === 'ldap') {
|
||||
ldapApi.listOUs().then(ous => setLdapImportOUs(Array.isArray(ous) ? ous : [])).catch(() => {});
|
||||
loadLdapUsers('');
|
||||
ldap.loadImportDialogData();
|
||||
}
|
||||
}, [importDialogOpen]);
|
||||
|
||||
@@ -236,7 +201,7 @@ export function SystemManager() {
|
||||
|
||||
// 执行 CSV 批量导入
|
||||
const handleBatchImport = async () => {
|
||||
setImporting(true);
|
||||
ldap.setImporting(true);
|
||||
try {
|
||||
const res = await userApi.batchImport({ users: importPreview, skip_existing: true });
|
||||
setImportResult(res);
|
||||
@@ -244,236 +209,10 @@ export function SystemManager() {
|
||||
} catch (error: any) {
|
||||
setImportResult({ code: 500, message: error?.message || '导入失败' });
|
||||
} finally {
|
||||
setImporting(false);
|
||||
ldap.setImporting(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载 LDAP 用户列表
|
||||
const loadLdapUsers = async (ouDn?: string) => {
|
||||
setLdapLoading(true);
|
||||
try {
|
||||
const res = await ldapApi.listUsers(ouDn);
|
||||
setLdapUsers(Array.isArray(res) ? res : []);
|
||||
setLdapSelected(new Set());
|
||||
} catch {
|
||||
setLdapUsers([]);
|
||||
} finally {
|
||||
setLdapLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 执行 LDAP 导入
|
||||
const handleLdapImport = async () => {
|
||||
let selected: any[] = [];
|
||||
if (selectedLDAPUsers.length > 0) {
|
||||
selected = ldapUsers.filter((u) => selectedLDAPUsers.includes(u.dn));
|
||||
} else {
|
||||
selected = ldapUsers; // 没有选择则导入全部
|
||||
}
|
||||
if (selected.length === 0) return;
|
||||
setImporting(true);
|
||||
try {
|
||||
const mapped = selected.map((u) => ({
|
||||
username: u.uid || '',
|
||||
nickname: u.cn || '',
|
||||
email: u.mail || '',
|
||||
}));
|
||||
const res = await ldapApi.batchImport(mapped);
|
||||
setImportFeedback(res?.message || `成功导入 ${selected.length} 个用户`);
|
||||
setImportResultOpen(true);
|
||||
setSelectedLDAPUsers([]);
|
||||
await loadUsers();
|
||||
} catch (error: any) {
|
||||
setImportFeedback('导入失败: ' + (error?.message || '未知错误'));
|
||||
setImportResultOpen(true);
|
||||
} finally {
|
||||
setImporting(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载 LDAP 配置
|
||||
const loadLdapConfig = async () => {
|
||||
try {
|
||||
const res = await ldapApi.getConfig();
|
||||
if (res && res.ldap_host) {
|
||||
setLdapConfig(res);
|
||||
setLdapForm({
|
||||
ldap_host: res.ldap_host || '',
|
||||
ldap_port: res.ldap_port || 389,
|
||||
use_ldaps: res.use_ldaps || false,
|
||||
admin_dn: res.admin_dn || '',
|
||||
admin_password: '',
|
||||
base_dn: res.base_dn || '',
|
||||
search_filter: res.search_filter || '',
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// No config yet
|
||||
}
|
||||
};
|
||||
|
||||
// 保存 LDAP 配置
|
||||
const handleLdapSave = async () => {
|
||||
setLdapSaving(true);
|
||||
try {
|
||||
await ldapApi.updateConfig(ldapForm);
|
||||
await loadLdapConfig();
|
||||
} catch (error) {
|
||||
console.error('Failed to save LDAP config:', error);
|
||||
} finally {
|
||||
setLdapSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 测试 LDAP 连接
|
||||
const handleLdapTest = async () => {
|
||||
setLdapTesting(true);
|
||||
setLdapTestResult(null);
|
||||
try {
|
||||
await ldapApi.updateConfig(ldapForm);
|
||||
const res = await ldapApi.testConnection();
|
||||
setLdapTestResult(res?.message || (res?.success ? '连接成功' : '连接失败'));
|
||||
} catch (error: any) {
|
||||
setLdapTestResult(error?.message || '连接失败');
|
||||
} finally {
|
||||
setLdapTesting(false);
|
||||
}
|
||||
};
|
||||
|
||||
// LDAP 账号管理函数
|
||||
const loadLdapOUs = async () => {
|
||||
try {
|
||||
const ous = await ldapApi.listOUs();
|
||||
setLdapOUs(ous || []);
|
||||
// 同时加载根 DN 下的用户
|
||||
if (!selectedOUDN && ldapConfig?.base_dn) {
|
||||
setSelectedOUDN(ldapConfig.base_dn);
|
||||
await loadLdapOUUsers(ldapConfig.base_dn);
|
||||
}
|
||||
} catch (e) { console.error('loadOUs', e); }
|
||||
};
|
||||
|
||||
const loadLdapOUUsers = async (ouDn?: string) => {
|
||||
try {
|
||||
const users = await ldapApi.listUsers(ouDn);
|
||||
setLdapUsers(users || []);
|
||||
} catch (e) { console.error('loadOUUsers', e); }
|
||||
};
|
||||
|
||||
const handleCreateOU = async () => {
|
||||
setLdapSaving(true);
|
||||
try {
|
||||
await ldapApi.createOU(ouForm);
|
||||
setCreateOUOpen(false);
|
||||
setOuForm({ ou_name: '', parent_dn: '', description: '' });
|
||||
await loadLdapOUs();
|
||||
} catch (e: any) {
|
||||
const msg = e?.message || '';
|
||||
if (msg.includes('Already Exists') || msg.includes('68')) {
|
||||
toast.error(`OU "${ouForm.ou_name}" 已存在,请使用其他名称`);
|
||||
} else {
|
||||
toast.error('创建失败: ' + msg);
|
||||
}
|
||||
} finally { setLdapSaving(false); }
|
||||
};
|
||||
|
||||
const handleCreateLDAPUser = async () => {
|
||||
setLdapSaving(true);
|
||||
try {
|
||||
await ldapApi.createUser({ ...newUser, ou_dn: newUser.ou_dn || selectedOUDN || ldapConfig?.base_dn });
|
||||
setCreateUserOpen(false);
|
||||
setNewUser({ username: '', password: '', display_name: '', email: '', ou_dn: '' });
|
||||
await loadLdapOUUsers(selectedOUDN);
|
||||
} catch (e: any) { toast.error(e?.message || '创建失败'); }
|
||||
finally { setLdapSaving(false); }
|
||||
};
|
||||
|
||||
const handleDeleteLDAPEntry = async (dn: string, silent = false) => {
|
||||
if (!silent) { const ok = await confirm({ title: '删除 LDAP 条目', description: `确定删除 ${dn}?`, confirmText: '删除', variant: 'destructive' }); if (!ok) return; }
|
||||
try {
|
||||
await ldapApi.deleteUser(dn);
|
||||
if (!silent) await loadLdapOUUsers(selectedOUDN);
|
||||
} catch (e: any) { if (!silent) toast.error(e?.message || '删除失败'); }
|
||||
};
|
||||
|
||||
const openEditLdapUser = (user: any) => {
|
||||
setEditLdapUser(user);
|
||||
setEditLdapForm({ cn: user.cn || '', mail: user.mail || '', phone: user.phone || '', title: user.title || '' });
|
||||
};
|
||||
|
||||
const handleUpdateLdapUser = async () => {
|
||||
if (!editLdapUser) return;
|
||||
try {
|
||||
await ldapApi.updateUser({ dn: editLdapUser.dn, ...editLdapForm });
|
||||
setEditLdapUser(null);
|
||||
await loadLdapOUUsers(selectedOUDN);
|
||||
} catch (e: any) { toast.error(e?.message || '修改失败'); }
|
||||
};
|
||||
|
||||
const handleLdapUserTest = async () => {
|
||||
setLdapUserTesting(true);
|
||||
setLdapUserTestResult(null);
|
||||
try {
|
||||
const res = await ldapApi.testConnection({ test_user: ldapTestUser, test_password: ldapTestPass });
|
||||
setLdapUserTestResult(res);
|
||||
} catch (e: any) {
|
||||
setLdapUserTestResult({ success: false, message: e?.message || '验证失败' });
|
||||
} finally { setLdapUserTesting(false); }
|
||||
};
|
||||
|
||||
// Settings tab props (LDAP management pass-through)
|
||||
const settingsTabProps = {
|
||||
ldapConfig,
|
||||
ldapForm,
|
||||
setLdapForm,
|
||||
ldapSaving,
|
||||
ldapTesting,
|
||||
ldapTestResult,
|
||||
handleLdapSave,
|
||||
handleLdapTest,
|
||||
ldapMgmtOpen,
|
||||
setLdapMgmtOpen,
|
||||
ldapOUs,
|
||||
selectedOUDN,
|
||||
setSelectedOUDN,
|
||||
ldapUsers,
|
||||
selectedLDAPUsers,
|
||||
setSelectedLDAPUsers,
|
||||
loadLdapOUs,
|
||||
loadLdapOUUsers,
|
||||
handleLdapImport,
|
||||
importing,
|
||||
importFeedback,
|
||||
importResultOpen,
|
||||
setImportResultOpen,
|
||||
createOUOpen,
|
||||
setCreateOUOpen,
|
||||
ouForm,
|
||||
setOuForm,
|
||||
handleCreateOU,
|
||||
createUserOpen,
|
||||
setCreateUserOpen,
|
||||
newUser,
|
||||
setNewUser,
|
||||
handleCreateLDAPUser,
|
||||
ldapUserTestOpen,
|
||||
setLdapUserTestOpen,
|
||||
ldapTestUser,
|
||||
setLdapTestUser,
|
||||
ldapTestPass,
|
||||
setLdapTestPass,
|
||||
ldapUserTesting,
|
||||
ldapUserTestResult,
|
||||
handleLdapUserTest,
|
||||
editLdapUser,
|
||||
setEditLdapUser,
|
||||
editLdapForm,
|
||||
setEditLdapForm,
|
||||
handleUpdateLdapUser,
|
||||
handleDeleteLDAPEntry,
|
||||
openEditLdapUser,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Page Header */}
|
||||
@@ -528,21 +267,21 @@ export function SystemManager() {
|
||||
setImportDialogOpen={setImportDialogOpen}
|
||||
importPreview={importPreview}
|
||||
setImportPreview={setImportPreview}
|
||||
importing={importing}
|
||||
importing={ldap.importing}
|
||||
importResult={importResult}
|
||||
setImportResult={setImportResult}
|
||||
handleCsvUpload={handleCsvUpload}
|
||||
handleBatchImport={handleBatchImport}
|
||||
ldapUsers={ldapUsers}
|
||||
ldapSelected={ldapSelected}
|
||||
setLdapSelected={setLdapSelected}
|
||||
ldapLoading={ldapLoading}
|
||||
ldapImportOUs={ldapImportOUs}
|
||||
ldapImportOUDN={ldapImportOUDN}
|
||||
setLdapImportOUDN={setLdapImportOUDN}
|
||||
loadLdapUsers={loadLdapUsers}
|
||||
handleLdapImport={handleLdapImport}
|
||||
setLdapUsers={setLdapUsers}
|
||||
ldapUsers={ldap.ldapUsers}
|
||||
ldapSelected={ldap.ldapSelected}
|
||||
setLdapSelected={ldap.setLdapSelected}
|
||||
ldapLoading={ldap.ldapLoading}
|
||||
ldapImportOUs={ldap.ldapImportOUs}
|
||||
ldapImportOUDN={ldap.ldapImportOUDN}
|
||||
setLdapImportOUDN={ldap.setLdapImportOUDN}
|
||||
loadLdapUsers={ldap.loadLdapUsers}
|
||||
handleLdapImport={ldap.handleLdapImport}
|
||||
setLdapUsers={ldap.setLdapUsers}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
@@ -561,7 +300,7 @@ export function SystemManager() {
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="settings" className="mt-4">
|
||||
<SystemSettingsTab {...settingsTabProps} />
|
||||
<SystemSettingsTab {...ldap.settingsTabProps} />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { ldapApi } from '@/services/api';
|
||||
import type { LdapFormData } from './SystemSettingsTab';
|
||||
|
||||
/**
|
||||
* useLdapManagement — 封装 SystemManager 中所有 LDAP 相关状态与业务逻辑
|
||||
*
|
||||
* 包含三大块:
|
||||
* 1. LDAP 配置管理(连接信息读写 + 测试连接)
|
||||
* 2. LDAP 账号管理(OU/用户 CRUD + 属性编辑 + 认证测试)
|
||||
* 3. LDAP 用户导入(导入弹窗用:OU 下拉 + 用户列表 + 批量导入)
|
||||
*
|
||||
* 另外持有 `importing` 状态,供 CSV 批量导入与 LDAP 导入共用。
|
||||
*
|
||||
* @param onUsersChanged 导入用户后回调(刷新本地用户列表)
|
||||
* // Logan.Li
|
||||
*/
|
||||
export function useLdapManagement(onUsersChanged: () => Promise<void> | void) {
|
||||
const confirm = useConfirm();
|
||||
|
||||
// ===== LDAP 用户导入(用户管理 Tab 的导入弹窗用) =====
|
||||
const [ldapUsers, setLdapUsers] = useState<any[]>([]);
|
||||
const [ldapSelected, setLdapSelected] = useState<Set<string>>(new Set());
|
||||
const [ldapLoading, setLdapLoading] = useState(false);
|
||||
const [ldapImportOUs, setLdapImportOUs] = useState<any[]>([]);
|
||||
const [ldapImportOUDN, setLdapImportOUDN] = useState('');
|
||||
|
||||
// ===== LDAP 配置 =====
|
||||
const [ldapConfig, setLdapConfig] = useState<any>(null);
|
||||
const [ldapForm, setLdapForm] = useState<LdapFormData>({
|
||||
ldap_host: '', ldap_port: 389, use_ldaps: false,
|
||||
admin_dn: '', admin_password: '', base_dn: '', search_filter: '',
|
||||
});
|
||||
const [ldapSaving, setLdapSaving] = useState(false);
|
||||
const [ldapTesting, setLdapTesting] = useState(false);
|
||||
const [ldapTestResult, setLdapTestResult] = useState<string | null>(null);
|
||||
const [ldapMgmtOpen, setLdapMgmtOpen] = useState(false);
|
||||
const [importFeedback, setImportFeedback] = useState<string | null>(null);
|
||||
const [importResultOpen, setImportResultOpen] = useState(false);
|
||||
|
||||
// ===== LDAP 账号管理 =====
|
||||
const [ldapOUs, setLdapOUs] = useState<any[]>([]);
|
||||
const [selectedOUDN, setSelectedOUDN] = useState('');
|
||||
const [selectedLDAPUsers, setSelectedLDAPUsers] = useState<string[]>([]);
|
||||
const [createOUOpen, setCreateOUOpen] = useState(false);
|
||||
const [createUserOpen, setCreateUserOpen] = useState(false);
|
||||
const [ouForm, setOuForm] = useState({ ou_name: '', parent_dn: '', description: '' });
|
||||
const [newUser, setNewUser] = useState({ username: '', password: '', display_name: '', email: '', ou_dn: '' });
|
||||
const [ldapUserTestOpen, setLdapUserTestOpen] = useState(false);
|
||||
const [ldapTestUser, setLdapTestUser] = useState('');
|
||||
const [ldapTestPass, setLdapTestPass] = useState('');
|
||||
const [ldapUserTesting, setLdapUserTesting] = useState(false);
|
||||
const [ldapUserTestResult, setLdapUserTestResult] = useState<any>(null);
|
||||
const [editLdapUser, setEditLdapUser] = useState<any>(null);
|
||||
const [editLdapForm, setEditLdapForm] = useState({ cn: '', mail: '', phone: '', title: '' });
|
||||
|
||||
// 导入进行中状态(CSV 与 LDAP 导入共用)
|
||||
const [importing, setImporting] = useState(false);
|
||||
|
||||
// ===== LDAP 配置相关 handler =====
|
||||
|
||||
/** 加载 LDAP 配置 // Logan.Li */
|
||||
const loadLdapConfig = async () => {
|
||||
try {
|
||||
const res = await ldapApi.getConfig();
|
||||
if (res && res.ldap_host) {
|
||||
setLdapConfig(res);
|
||||
setLdapForm({
|
||||
ldap_host: res.ldap_host || '',
|
||||
ldap_port: res.ldap_port || 389,
|
||||
use_ldaps: res.use_ldaps || false,
|
||||
admin_dn: res.admin_dn || '',
|
||||
admin_password: '',
|
||||
base_dn: res.base_dn || '',
|
||||
search_filter: res.search_filter || '',
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// 暂无配置
|
||||
}
|
||||
};
|
||||
|
||||
/** 保存 LDAP 配置 // Logan.Li */
|
||||
const handleLdapSave = async () => {
|
||||
setLdapSaving(true);
|
||||
try {
|
||||
await ldapApi.updateConfig(ldapForm);
|
||||
await loadLdapConfig();
|
||||
} catch (error) {
|
||||
console.error('Failed to save LDAP config:', error);
|
||||
} finally {
|
||||
setLdapSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
/** 测试 LDAP 连接 // Logan.Li */
|
||||
const handleLdapTest = async () => {
|
||||
setLdapTesting(true);
|
||||
setLdapTestResult(null);
|
||||
try {
|
||||
await ldapApi.updateConfig(ldapForm);
|
||||
const res = await ldapApi.testConnection();
|
||||
setLdapTestResult(res?.message || (res?.success ? '连接成功' : '连接失败'));
|
||||
} catch (error: any) {
|
||||
setLdapTestResult(error?.message || '连接失败');
|
||||
} finally {
|
||||
setLdapTesting(false);
|
||||
}
|
||||
};
|
||||
|
||||
// ===== LDAP 账号管理相关 handler =====
|
||||
|
||||
/** 加载指定 OU 下的用户 // Logan.Li */
|
||||
const loadLdapOUUsers = async (ouDn?: string) => {
|
||||
try {
|
||||
const users = await ldapApi.listUsers(ouDn);
|
||||
setLdapUsers(users || []);
|
||||
} catch (e) { console.error('loadOUUsers', e); }
|
||||
};
|
||||
|
||||
/** 加载 OU 列表(含根 DN 用户) // Logan.Li */
|
||||
const loadLdapOUs = async () => {
|
||||
try {
|
||||
const ous = await ldapApi.listOUs();
|
||||
setLdapOUs(ous || []);
|
||||
// 同时加载根 DN 下的用户
|
||||
if (!selectedOUDN && ldapConfig?.base_dn) {
|
||||
setSelectedOUDN(ldapConfig.base_dn);
|
||||
await loadLdapOUUsers(ldapConfig.base_dn);
|
||||
}
|
||||
} catch (e) { console.error('loadOUs', e); }
|
||||
};
|
||||
|
||||
/** 创建 OU // Logan.Li */
|
||||
const handleCreateOU = async () => {
|
||||
setLdapSaving(true);
|
||||
try {
|
||||
await ldapApi.createOU(ouForm);
|
||||
setCreateOUOpen(false);
|
||||
setOuForm({ ou_name: '', parent_dn: '', description: '' });
|
||||
await loadLdapOUs();
|
||||
} catch (e: any) {
|
||||
const msg = e?.message || '';
|
||||
if (msg.includes('Already Exists') || msg.includes('68')) {
|
||||
toast.error(`OU "${ouForm.ou_name}" 已存在,请使用其他名称`);
|
||||
} else {
|
||||
toast.error('创建失败: ' + msg);
|
||||
}
|
||||
} finally { setLdapSaving(false); }
|
||||
};
|
||||
|
||||
/** 创建 LDAP 用户 // Logan.Li */
|
||||
const handleCreateLDAPUser = async () => {
|
||||
setLdapSaving(true);
|
||||
try {
|
||||
await ldapApi.createUser({ ...newUser, ou_dn: newUser.ou_dn || selectedOUDN || ldapConfig?.base_dn });
|
||||
setCreateUserOpen(false);
|
||||
setNewUser({ username: '', password: '', display_name: '', email: '', ou_dn: '' });
|
||||
await loadLdapOUUsers(selectedOUDN);
|
||||
} catch (e: any) { toast.error(e?.message || '创建失败'); }
|
||||
finally { setLdapSaving(false); }
|
||||
};
|
||||
|
||||
/** 删除 LDAP 条目 // Logan.Li */
|
||||
const handleDeleteLDAPEntry = async (dn: string, silent = false) => {
|
||||
if (!silent) {
|
||||
const ok = await confirm({ title: '删除 LDAP 条目', description: `确定删除 ${dn}?`, confirmText: '删除', variant: 'destructive' });
|
||||
if (!ok) return;
|
||||
}
|
||||
try {
|
||||
await ldapApi.deleteUser(dn);
|
||||
if (!silent) await loadLdapOUUsers(selectedOUDN);
|
||||
} catch (e: any) { if (!silent) toast.error(e?.message || '删除失败'); }
|
||||
};
|
||||
|
||||
/** 打开 LDAP 用户编辑 // Logan.Li */
|
||||
const openEditLdapUser = (user: any) => {
|
||||
setEditLdapUser(user);
|
||||
setEditLdapForm({ cn: user.cn || '', mail: user.mail || '', phone: user.phone || '', title: user.title || '' });
|
||||
};
|
||||
|
||||
/** 更新 LDAP 用户属性 // Logan.Li */
|
||||
const handleUpdateLdapUser = async () => {
|
||||
if (!editLdapUser) return;
|
||||
try {
|
||||
await ldapApi.updateUser({ dn: editLdapUser.dn, ...editLdapForm });
|
||||
setEditLdapUser(null);
|
||||
await loadLdapOUUsers(selectedOUDN);
|
||||
} catch (e: any) { toast.error(e?.message || '修改失败'); }
|
||||
};
|
||||
|
||||
/** LDAP 账号验证测试 // Logan.Li */
|
||||
const handleLdapUserTest = async () => {
|
||||
setLdapUserTesting(true);
|
||||
setLdapUserTestResult(null);
|
||||
try {
|
||||
const res = await ldapApi.testConnection({ test_user: ldapTestUser, test_password: ldapTestPass });
|
||||
setLdapUserTestResult(res);
|
||||
} catch (e: any) {
|
||||
setLdapUserTestResult({ success: false, message: e?.message || '验证失败' });
|
||||
} finally { setLdapUserTesting(false); }
|
||||
};
|
||||
|
||||
// ===== LDAP 用户导入相关 handler =====
|
||||
|
||||
/** 加载 LDAP 用户列表(导入弹窗用) // Logan.Li */
|
||||
const loadLdapUsers = async (ouDn?: string) => {
|
||||
setLdapLoading(true);
|
||||
try {
|
||||
const res = await ldapApi.listUsers(ouDn);
|
||||
setLdapUsers(Array.isArray(res) ? res : []);
|
||||
setLdapSelected(new Set());
|
||||
} catch {
|
||||
setLdapUsers([]);
|
||||
} finally {
|
||||
setLdapLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
/** 执行 LDAP 批量导入 // Logan.Li */
|
||||
const handleLdapImport = async () => {
|
||||
let selected: any[] = [];
|
||||
if (selectedLDAPUsers.length > 0) {
|
||||
selected = ldapUsers.filter((u) => selectedLDAPUsers.includes(u.dn));
|
||||
} else {
|
||||
selected = ldapUsers; // 没有选择则导入全部
|
||||
}
|
||||
if (selected.length === 0) return;
|
||||
setImporting(true);
|
||||
try {
|
||||
const mapped = selected.map((u) => ({
|
||||
username: u.uid || '',
|
||||
nickname: u.cn || '',
|
||||
email: u.mail || '',
|
||||
}));
|
||||
const res = await ldapApi.batchImport(mapped);
|
||||
setImportFeedback(res?.message || `成功导入 ${selected.length} 个用户`);
|
||||
setImportResultOpen(true);
|
||||
setSelectedLDAPUsers([]);
|
||||
await onUsersChanged();
|
||||
} catch (error: any) {
|
||||
setImportFeedback('导入失败: ' + (error?.message || '未知错误'));
|
||||
setImportResultOpen(true);
|
||||
} finally {
|
||||
setImporting(false);
|
||||
}
|
||||
};
|
||||
|
||||
/** LDAP 导入弹窗打开时加载 OU 和用户列表 // Logan.Li */
|
||||
const loadImportDialogData = () => {
|
||||
ldapApi.listOUs()
|
||||
.then((ous) => setLdapImportOUs(Array.isArray(ous) ? ous : []))
|
||||
.catch(() => {});
|
||||
loadLdapUsers('');
|
||||
};
|
||||
|
||||
// ===== 构造传递给 SystemSettingsTab 的 props 对象 =====
|
||||
const settingsTabProps = {
|
||||
ldapConfig,
|
||||
ldapForm,
|
||||
setLdapForm,
|
||||
ldapSaving,
|
||||
ldapTesting,
|
||||
ldapTestResult,
|
||||
handleLdapSave,
|
||||
handleLdapTest,
|
||||
ldapMgmtOpen,
|
||||
setLdapMgmtOpen,
|
||||
ldapOUs,
|
||||
selectedOUDN,
|
||||
setSelectedOUDN,
|
||||
ldapUsers,
|
||||
selectedLDAPUsers,
|
||||
setSelectedLDAPUsers,
|
||||
loadLdapOUs,
|
||||
loadLdapOUUsers,
|
||||
handleLdapImport,
|
||||
importing,
|
||||
importFeedback,
|
||||
importResultOpen,
|
||||
setImportResultOpen,
|
||||
createOUOpen,
|
||||
setCreateOUOpen,
|
||||
ouForm,
|
||||
setOuForm,
|
||||
handleCreateOU,
|
||||
createUserOpen,
|
||||
setCreateUserOpen,
|
||||
newUser,
|
||||
setNewUser,
|
||||
handleCreateLDAPUser,
|
||||
ldapUserTestOpen,
|
||||
setLdapUserTestOpen,
|
||||
ldapTestUser,
|
||||
setLdapTestUser,
|
||||
ldapTestPass,
|
||||
setLdapTestPass,
|
||||
ldapUserTesting,
|
||||
ldapUserTestResult,
|
||||
handleLdapUserTest,
|
||||
editLdapUser,
|
||||
setEditLdapUser,
|
||||
editLdapForm,
|
||||
setEditLdapForm,
|
||||
handleUpdateLdapUser,
|
||||
handleDeleteLDAPEntry,
|
||||
openEditLdapUser,
|
||||
};
|
||||
|
||||
return {
|
||||
// LDAP 用户导入(用户管理 Tab)
|
||||
ldapUsers,
|
||||
setLdapUsers,
|
||||
ldapSelected,
|
||||
setLdapSelected,
|
||||
ldapLoading,
|
||||
ldapImportOUs,
|
||||
ldapImportOUDN,
|
||||
setLdapImportOUDN,
|
||||
loadLdapUsers,
|
||||
handleLdapImport,
|
||||
loadImportDialogData,
|
||||
// 导入状态(CSV + LDAP 共用)
|
||||
importing,
|
||||
setImporting,
|
||||
importFeedback,
|
||||
importResultOpen,
|
||||
setImportResultOpen,
|
||||
// 初始化
|
||||
loadLdapConfig,
|
||||
// 系统设置 Tab
|
||||
settingsTabProps,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user