import {CurdColumn, CurdPage} from "../../../../components/curd"; import {useCallback, useMemo, useState} from "react"; import {LDAP, LDAPApis} from "../../../../api/ldap.ts"; import {ICurdConfig} from "../../../../components/curd/types.ts"; import {Alert, Button} from "antd"; import './index.less' import {Link} from "react-router-dom"; import {useRouteLoaderData} from "react-router"; import {SyncOutlined} from "@ant-design/icons"; import {isNullOrTrue, Message} from "auto-antd"; import {UserAttributesText} from "../components/UserAttributes.tsx"; import {safeParse} from "../../../../utils/json.ts"; const columns: CurdColumn[] = [ { key: 'id', title: 'ID', type: 'string', disabled: true, required: false, width: 50, addable: false, }, { key: 'account', title: '账号(uid)', type: 'string', editable: false, placeholder: '账号,全局唯一,不可重复', required: true, width: 120, addable: true, }, { key: 'givenName', title: '姓', type: 'string', editable: true, required: true, width: 120, hidden: true, addable: true, }, { key: 'sn', title: '名', type: 'string', editable: true, required: true, width: 120, hidden: true, addable: true, }, { key: 'objectClass', title: 'objectClass', type: 'select', editable: true, required: true, width: 120, hidden: true, addable: true, option:['top','inetOrgPerson','organizationalPerson','person'], multiple: true, }, { key: 'dn', title: 'DN', type: 'string', placeholder: 'eg. cn=Abc,dc=tonyandmoney,dc=cn', width: 150, addable: false, editable: false, editHide: true, }, { key: 'organize', title: '上级(DN)', type: 'string', placeholder: 'eg. ou=users,dc=tonyandmoney,dc=cn', width: 150, }, { key: 'mail', title: '邮箱', type: 'string', width: 150 }, { key: 'password', title: '密码', type: 'password', width: 150, addable: true, }, { key: 'attributes', title: '更多属性', type: 'attributes', render: (v: string)=>(), hidden: true, required: false, }, { key: 'remark', title: '备注', type: 'textarea', required: false, } ] const toObjKeys = ['givenName','sn', 'objectClass'] const delKeys = ['cn','mail','userPassword','uid'] const parseUser = (user: LDAP.User) => { const attrs = safeParse(user.attributes, []) console.log('attrs', attrs) const attrList = [] for (const attr of attrs) { attr.Value = Array.isArray(attr.Values) ? attr.Values[0] : undefined if (attr.Name == 'objectClass'){ attr.Value = attr.Values || [] } if (toObjKeys.includes(attr.Name)){ (user as any)[attr.Name] = attr.Value }else if (!delKeys.includes(attr.Name)){ attrList.push(attr) } } return { ...user, attributes: attrList, } as LDAP.User } const stringifyUser = (user: Partial) => { const attributes = [] for (const attr of (user.attributes as any[])) { attributes.push({ Name: attr.Name, Values: isNullOrTrue(attr.Value) ? [attr.Values] : [] }) } for (const k of toObjKeys){ const v = (user as any)[k] if (isNullOrTrue(v)) { attributes.push({ Name: k, Values: [v] }) } } return { ...user, attributes: JSON.stringify(attributes), } } const serverConfig: ICurdConfig = { editDialogWidth: 700, labelSpan: 4, } /** * 用户列表的操作 * @constructor */ export const List = () => { const server = useRouteLoaderData("LDAPServerUsers") as LDAP.Server const [loading, setLoading] = useState(false) const [success,setSuccess] = useState('') const getList = useCallback((query: any) => { console.log('server...', server) return LDAPApis.getUsers({ ...query, serverKey: server.key, }).then(res => { console.log('server', res) return res.data.data }) }, [server]) const getDetail = (data: Partial) => { if (!data.id) { return Promise.resolve({} as LDAP.User) } return LDAPApis.getUserDetail(data.id).then(res => { if (res.data?.data) { const user = parseUser(res.data.data); console.log('user', user) return user; } throw new Error('该服务不存在!') }) } const onSaveUser = (data: Partial) => { const user = stringifyUser(data) if (data.id){ return LDAPApis.saveUser(user) .then(res => { return res.data.data as LDAP.User; }) } return LDAPApis.add(user) .then(res => { return res.data.data as LDAP.User; }) } const syncUsers = () => { setLoading(true) LDAPApis.syncUsers({serverKey: server.key}) .then(res => { console.log('sync users', res) if (res.data?.data) { setSuccess(`操作成功:同步:${res.data.data.count}条数据!`) } else { Message.warning(res.data.msg || '同步异常!') } }).finally(() => { setLoading(false) }) } const operationRender = (record: LDAP.User, _: number) => { return (<> ) } const config = useMemo(() => { return { ...serverConfig, operationRender } as ICurdConfig }, []) return (<> { success ? (setSuccess('')}/> ) : null } } onSave={onSaveUser} config={config}/> ) }