|
@@ -7,8 +7,9 @@ import './index.less'
|
|
|
import {Link} from "react-router-dom";
|
|
|
import {useRouteLoaderData} from "react-router";
|
|
|
import {SyncOutlined} from "@ant-design/icons";
|
|
|
-import {Message} from "auto-antd";
|
|
|
-import {UserAttributes} from "../components/UserAttributes.tsx";
|
|
|
+import {isNullOrTrue, Message} from "auto-antd";
|
|
|
+import {UserAttributesText} from "../components/UserAttributes.tsx";
|
|
|
+import {safeParse} from "../../../../utils/json.ts";
|
|
|
|
|
|
const columns: CurdColumn[] = [
|
|
|
{
|
|
@@ -17,23 +18,67 @@ const columns: CurdColumn[] = [
|
|
|
type: 'string',
|
|
|
disabled: true,
|
|
|
required: false,
|
|
|
- width: 50
|
|
|
+ width: 50,
|
|
|
+ addable: false,
|
|
|
},
|
|
|
{
|
|
|
key: 'account',
|
|
|
title: '账号(uid)',
|
|
|
type: 'string',
|
|
|
- disabled: true,
|
|
|
- placeholder: '服务唯一编码,自动生成',
|
|
|
- required: false,
|
|
|
- width: 120
|
|
|
+ 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
|
|
|
+ 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',
|
|
@@ -41,11 +86,20 @@ const columns: CurdColumn[] = [
|
|
|
type: 'string',
|
|
|
width: 150
|
|
|
},
|
|
|
+ {
|
|
|
+ key: 'password',
|
|
|
+ title: '密码',
|
|
|
+ type: 'password',
|
|
|
+ width: 150,
|
|
|
+ addable: true,
|
|
|
+ },
|
|
|
{
|
|
|
key: 'attributes',
|
|
|
- title: '详细属性',
|
|
|
- type: 'string',
|
|
|
- render: (_: any, record: LDAP.User) => <UserAttributes user={record} />
|
|
|
+ title: '更多属性',
|
|
|
+ type: 'attributes',
|
|
|
+ render: (v: string)=>(<UserAttributesText value={v}/>),
|
|
|
+ hidden: true,
|
|
|
+ required: false,
|
|
|
},
|
|
|
{
|
|
|
key: 'remark',
|
|
@@ -55,9 +109,57 @@ const columns: CurdColumn[] = [
|
|
|
}
|
|
|
]
|
|
|
|
|
|
+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<LDAP.User>) => {
|
|
|
+ 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<LDAP.User> = {
|
|
|
- editDialogWidth: 500,
|
|
|
- labelSpan: 6,
|
|
|
+ editDialogWidth: 700,
|
|
|
+ labelSpan: 4,
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -89,14 +191,23 @@ export const List = () => {
|
|
|
}
|
|
|
return LDAPApis.getUserDetail(data.id).then(res => {
|
|
|
if (res.data?.data) {
|
|
|
- return res.data.data;
|
|
|
+ const user = parseUser(res.data.data);
|
|
|
+ console.log('user', user)
|
|
|
+ return user;
|
|
|
}
|
|
|
throw new Error('该服务不存在!')
|
|
|
})
|
|
|
}
|
|
|
|
|
|
const onSaveUser = (data: Partial<LDAP.User>) => {
|
|
|
- return LDAPApis.saveUser(data)
|
|
|
+ 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;
|
|
|
})
|