Просмотр исходного кода

!1030 域用户同步以及用户界面配置域账号
Merge pull request !1030 from 冰魄少年/next

zuohuaijun 2 лет назад
Родитель
Сommit
8fd85f9309

+ 13 - 1
Admin.NET/Admin.NET.Core/Entity/SysLdap.cs

@@ -54,7 +54,7 @@ public class SysLdap : EntityTenant
     /// </summary>
     /// </summary>
     [SugarColumn(ColumnDescription = "用户过滤规则", Length = 128)]
     [SugarColumn(ColumnDescription = "用户过滤规则", Length = 128)]
     [Required]
     [Required]
-    public virtual string AuthFilter { get; set; } = "sAMAccountName";
+    public virtual string AuthFilter { get; set; } = "sAMAccountName=%s";
 
 
     /// <summary>
     /// <summary>
     /// Ldap版本
     /// Ldap版本
@@ -62,6 +62,18 @@ public class SysLdap : EntityTenant
     [SugarColumn(ColumnDescription = "Ldap版本")]
     [SugarColumn(ColumnDescription = "Ldap版本")]
     public int Version { get; set; }
     public int Version { get; set; }
 
 
+    /// <summary>
+    /// 绑定域账号字段属性值
+    /// </summary>
+    [SugarColumn(ColumnDescription = "绑定域账号字段属性值", Length = 24)]
+    public virtual string BindAttrAccount { get; set; } = "sAMAccountName";
+
+    /// <summary>
+    /// 绑定用户employeeID属性值
+    /// </summary>
+    [SugarColumn(ColumnDescription = "绑定用户employeeID属性值", Length = 24)]
+    public virtual string BindAttrEmployeeId { get; set; } = "employeeID";
+
     /// <summary>
     /// <summary>
     /// 状态
     /// 状态
     /// </summary>
     /// </summary>

+ 1 - 0
Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs

@@ -88,6 +88,7 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
             new SysMenu{ Id=1310000000194, Pid=1310000000191, Title="编辑", Permission="sysLdap:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
             new SysMenu{ Id=1310000000194, Pid=1310000000191, Title="编辑", Permission="sysLdap:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
             new SysMenu{ Id=1310000000195, Pid=1310000000191, Title="增加", Permission="sysLdap:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
             new SysMenu{ Id=1310000000195, Pid=1310000000191, Title="增加", Permission="sysLdap:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
             new SysMenu{ Id=1310000000196, Pid=1310000000191, Title="删除", Permission="sysLdap:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
             new SysMenu{ Id=1310000000196, Pid=1310000000191, Title="删除", Permission="sysLdap:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
+            new SysMenu{ Id=1310000000197, Pid=1310000000191, Title="同步域账户", Permission="sysLdap:userSync", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=150 },
 
 
             new SysMenu{ Id=1310000000301, Pid=0, Title="平台管理", Path="/platform", Name="platform", Component="Layout", Icon="ele-Menu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=11000 },
             new SysMenu{ Id=1310000000301, Pid=0, Title="平台管理", Path="/platform", Name="platform", Component="Layout", Icon="ele-Menu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=11000 },
 
 

+ 8 - 0
Admin.NET/Admin.NET.Core/Service/Auth/Dto/SysLdapInput.cs

@@ -38,4 +38,12 @@ public class DeleteSysLdapInput : BaseIdInput
 
 
 public class DetailSysLdapInput : BaseIdInput
 public class DetailSysLdapInput : BaseIdInput
 {
 {
+}
+
+public class QueryByIdSysLdapInput : BaseIdInput
+{
+}
+
+public class UserSyncIdSysLdapInput:BaseIdInput
+{
 }
 }

+ 109 - 5
Admin.NET/Admin.NET.Core/Service/Auth/SysLdapService.cs

@@ -17,12 +17,12 @@ namespace Admin.NET.Core;
 public class SysLdapService : IDynamicApiController, ITransient
 public class SysLdapService : IDynamicApiController, ITransient
 {
 {
     private readonly SqlSugarRepository<SysLdap> _sysLdapRep;
     private readonly SqlSugarRepository<SysLdap> _sysLdapRep;
-    private readonly SqlSugarRepository<SysUserLdap> _sysUserLdapRep;
+    private readonly SysUserLdapService _sysUserLdapService;
 
 
-    public SysLdapService(SqlSugarRepository<SysLdap> rep, SqlSugarRepository<SysUserLdap> sysUserLdapRep)
+    public SysLdapService(SqlSugarRepository<SysLdap> rep, SysUserLdapService sysUserLdapService)
     {
     {
         _sysLdapRep = rep;
         _sysLdapRep = rep;
-        _sysUserLdapRep = sysUserLdapRep;
+        _sysUserLdapService = sysUserLdapService;
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -120,7 +120,7 @@ public class SysLdapService : IDynamicApiController, ITransient
         {
         {
             ldapConn.Connect(ldap.Host, ldap.Port);
             ldapConn.Connect(ldap.Host, ldap.Port);
             ldapConn.Bind(ldap.Version, ldap.BindDn, ldap.BindPass);
             ldapConn.Bind(ldap.Version, ldap.BindDn, ldap.BindPass);
-            var userEntitys = ldapConn.Search(ldap.BaseDn, LdapConnection.ScopeSub, $"{ldap.AuthFilter}={account}", null, false);
+            var userEntitys = ldapConn.Search(ldap.BaseDn, LdapConnection.ScopeSub, ldap.AuthFilter.Replace("$s", account), null, false);
             string dn = string.Empty;
             string dn = string.Empty;
             while (userEntitys.HasMore())
             while (userEntitys.HasMore())
             {
             {
@@ -145,7 +145,6 @@ public class SysLdapService : IDynamicApiController, ITransient
                     throw Oops.Oh(ErrorCodeEnum.D0009);
                     throw Oops.Oh(ErrorCodeEnum.D0009);
                 case LdapException.InvalidCredentials:
                 case LdapException.InvalidCredentials:
                     return false;
                     return false;
-
                 default:
                 default:
                     throw Oops.Oh(e.Message);
                     throw Oops.Oh(e.Message);
             }
             }
@@ -156,4 +155,109 @@ public class SysLdapService : IDynamicApiController, ITransient
         }
         }
         return true;
         return true;
     }
     }
+
+    /// <summary>
+    /// 同步域用户
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [HttpPost]
+    [ApiDescriptionSettings(Name = "UserSync")]
+    public async Task UserSync(UserSyncIdSysLdapInput input)
+    {
+        var ldap = await _sysLdapRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
+        LdapConnection ldapConn = new LdapConnection();
+        try
+        {
+            ldapConn.Connect(ldap.Host, ldap.Port);
+            ldapConn.Bind(ldap.Version, ldap.BindDn, ldap.BindPass);
+            var userEntitys = ldapConn.Search(ldap.BaseDn, LdapConnection.ScopeOne, "(objectClass=*)", null, false);
+            string dn = string.Empty;
+            var listUserLdap = new List<SysUserLdap>();
+            while (userEntitys.HasMore())
+            {
+                LdapEntry entity;
+                try
+                {
+                    entity = userEntitys.Next();
+                    if (entity == null) continue;
+                }
+                catch (LdapException)
+                {
+                    continue;
+                }
+                var attrs = entity.GetAttributeSet();
+                if (attrs.Count == 0 || attrs.ContainsKey("OU"))
+                    LdapUserSearchDn(ldapConn, ldap, listUserLdap, entity.Dn);
+                else
+                {
+                    var sysUserLdap = new SysUserLdap
+                    {
+                        Account = !attrs.ContainsKey(ldap.BindAttrAccount) ? null : attrs.GetAttribute(ldap.BindAttrAccount)?.StringValue,
+                        EmployeeId = !attrs.ContainsKey(ldap.BindAttrEmployeeId) ? null : attrs.GetAttribute(ldap.BindAttrEmployeeId)?.StringValue
+                    };
+                    if (string.IsNullOrEmpty(sysUserLdap.EmployeeId)) continue;
+                    listUserLdap.Add(sysUserLdap);
+                }
+            }
+            if (listUserLdap.Count == 0)
+                return;           
+            await _sysUserLdapService.InsertUserLdapsAsync(ldap.TenantId.Value, listUserLdap);
+        }
+        catch (LdapException e)
+        {
+            switch (e.ResultCode)
+            {
+                case LdapException.NoSuchObject:
+                case LdapException.NoSuchAttribute:
+                    throw Oops.Oh(ErrorCodeEnum.D0009);
+                case LdapException.InvalidCredentials:
+                default:
+                    throw Oops.Oh(e.Message);
+            }
+        }
+        finally
+        {
+            ldapConn.Disconnect();
+        }
+    }
+
+    /// <summary>
+    /// 域用户遍历查询
+    /// </summary>
+    /// <param name="conn"></param>
+    /// <param name="ldap"></param>
+    /// <param name="listUserLdap"></param>
+    /// <param name="baseDn"></param>
+    private void LdapUserSearchDn(LdapConnection conn, SysLdap ldap, List<SysUserLdap> listUserLdap, string baseDn)
+    {
+        var userEntitys = conn.Search(baseDn, LdapConnection.ScopeOne, "(objectClass=*)", null, false);
+        string dn = string.Empty;
+        while (userEntitys.HasMore())
+        {
+            LdapEntry entity;
+            try
+            {
+                entity = userEntitys.Next();
+                if (entity == null) continue;
+            }
+            catch (LdapException)
+            {
+                continue;
+            }
+            var attrs = entity.GetAttributeSet();
+            if (attrs.Count == 0 || attrs.ContainsKey("OU"))
+                LdapUserSearchDn(conn, ldap, listUserLdap, entity.Dn);
+            else
+            {
+                var sysUserLdap = new SysUserLdap
+                {
+                    Account = !attrs.ContainsKey(ldap.BindAttrAccount) ? null : attrs.GetAttribute(ldap.BindAttrAccount)?.StringValue,
+                    EmployeeId = !attrs.ContainsKey(ldap.BindAttrEmployeeId) ? null : attrs.GetAttribute(ldap.BindAttrEmployeeId)?.StringValue
+                };
+                if (string.IsNullOrEmpty(sysUserLdap.EmployeeId)) continue;
+                listUserLdap.Add(sysUserLdap);
+            }
+        }
+    }
 }
 }

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/User/Dto/UserInput.cs

@@ -62,6 +62,11 @@ public class AddUserInput : SysUser
     [Required(ErrorMessage = "真实姓名不能为空")]
     [Required(ErrorMessage = "真实姓名不能为空")]
     public override string RealName { get; set; }
     public override string RealName { get; set; }
 
 
+    /// <summary>
+    /// 域用户
+    /// </summary>
+    public string DomainAccount { get; set; }
+
     /// <summary>
     /// <summary>
     /// 角色集合
     /// 角色集合
     /// </summary>
     /// </summary>

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/User/Dto/UserOutput.cs

@@ -24,4 +24,9 @@ public class UserOutput : SysUser
     /// 角色名称
     /// 角色名称
     /// </summary>
     /// </summary>
     public string RoleName { get; set; }
     public string RoleName { get; set; }
+    
+    /// <summary>
+    /// 域用户
+    /// </summary>
+    public string DomainAccount { get; set; }
 }
 }

+ 68 - 0
Admin.NET/Admin.NET.Core/Service/User/SysUserLdapService.cs

@@ -0,0 +1,68 @@
+// 大名科技(天津)有限公司 版权所有
+//
+// 此源代码遵循位于源代码树根目录中的 LICENSE 文件的许可证
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动
+//
+// 任何基于本项目二次开发而产生的一切法律纠纷和责任,均与作者无关
+
+using Furion.Localization;
+
+namespace Admin.NET.Core.Service;
+/// <summary>
+/// 用户域账号对照服务
+/// </summary>
+[ApiDescriptionSettings(Order = 490)]
+public class SysUserLdapService : IDynamicApiController, ITransient
+{
+    private readonly SqlSugarRepository<SysUserLdap> _sysUserLdapRep;
+    private readonly ISqlSugarClient _sqlSugarClient;
+    public SysUserLdapService(SqlSugarRepository<SysUserLdap> sysUserLdapRep, ISqlSugarClient sqlSugarClient)
+    {
+        _sysUserLdapRep = sysUserLdapRep;
+        _sqlSugarClient = sqlSugarClient;
+    }
+
+    /// <summary>
+    /// 批量插入数据
+    /// </summary>
+    /// <param name="tenantId"></param>
+    /// <param name="sysUserLdaps"></param>
+    /// <returns></returns>
+    public async Task InsertUserLdapsAsync(long tenantId, List<SysUserLdap> sysUserLdaps)
+    {
+        await _sysUserLdapRep.DeleteAsync(u => u.TenantId == tenantId);
+        await _sysUserLdapRep.InsertRangeAsync(sysUserLdaps);
+        await _sqlSugarClient.Updateable<SysUserLdap>()
+                             .InnerJoin<SysUser>((l, u) => l.EmployeeId == u.Account && u.Status == StatusEnum.Enable && u.IsDelete == false && l.IsDelete == false)
+                             .SetColumns((l, u) => new SysUserLdap { UserId = u.Id })
+                             .ExecuteCommandAsync();
+    }
+
+    /// <summary>
+    /// 批量插入数据
+    /// </summary>
+    /// <param name="tenantId"></param>
+    /// <param name="userId"></param>
+    /// <param name="account"></param>
+    /// <param name="domainAccount"></param>
+    /// <returns></returns>
+    public async Task AddUserLdapAsync(long tenantId, long userId, string account, string domainAccount)
+    {
+        var userLdap = _sysUserLdapRep.GetFirstAsync(u => u.TenantId == tenantId && u.IsDelete == false && (u.Account == account || u.UserId == userId || u.EmployeeId == domainAccount));
+        if (userLdap != null)
+            await _sysUserLdapRep.DeleteByIdAsync(userLdap.Id);
+        if (!string.IsNullOrWhiteSpace(domainAccount))
+            await _sysUserLdapRep.InsertAsync(new SysUserLdap { EmployeeId = account, TenantId = tenantId, UserId = userId, Account = domainAccount });
+    }
+
+    /// <summary>
+    /// 删除用户关联数据
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <returns></returns>
+    public async Task DeleteUserLdapByUserId(long userId)
+    {
+        await _sysUserLdapRep.DeleteAsync(u => u.UserId == userId);
+    }
+}

+ 14 - 3
Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs

@@ -22,6 +22,7 @@ public class SysUserService : IDynamicApiController, ITransient
     private readonly SysConfigService _sysConfigService;
     private readonly SysConfigService _sysConfigService;
     private readonly SysOnlineUserService _sysOnlineUserService;
     private readonly SysOnlineUserService _sysOnlineUserService;
     private readonly SysCacheService _sysCacheService;
     private readonly SysCacheService _sysCacheService;
+    private readonly SysUserLdapService _sysUserLdapService;
 
 
     public SysUserService(UserManager userManager,
     public SysUserService(UserManager userManager,
         SqlSugarRepository<SysUser> sysUserRep,
         SqlSugarRepository<SysUser> sysUserRep,
@@ -30,7 +31,8 @@ public class SysUserService : IDynamicApiController, ITransient
         SysUserRoleService sysUserRoleService,
         SysUserRoleService sysUserRoleService,
         SysConfigService sysConfigService,
         SysConfigService sysConfigService,
         SysOnlineUserService sysOnlineUserService,
         SysOnlineUserService sysOnlineUserService,
-        SysCacheService sysCacheService)
+        SysCacheService sysCacheService,
+        SysUserLdapService sysUserLdapService)
     {
     {
         _userManager = userManager;
         _userManager = userManager;
         _sysUserRep = sysUserRep;
         _sysUserRep = sysUserRep;
@@ -40,6 +42,7 @@ public class SysUserService : IDynamicApiController, ITransient
         _sysConfigService = sysConfigService;
         _sysConfigService = sysConfigService;
         _sysOnlineUserService = sysOnlineUserService;
         _sysOnlineUserService = sysOnlineUserService;
         _sysCacheService = sysCacheService;
         _sysCacheService = sysCacheService;
+        _sysUserLdapService = sysUserLdapService;
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -76,7 +79,8 @@ public class SysUserService : IDynamicApiController, ITransient
             {
             {
                 OrgName = a.Name,
                 OrgName = a.Name,
                 PosName = b.Name,
                 PosName = b.Name,
-                RoleName = SqlFunc.Subqueryable<SysUserRole>().LeftJoin<SysRole>((m, n) => m.RoleId == n.Id).Where(m => m.UserId == u.Id).SelectStringJoin((m, n) => n.Name, ",")
+                RoleName = SqlFunc.Subqueryable<SysUserRole>().LeftJoin<SysRole>((m, n) => m.RoleId == n.Id).Where(m => m.UserId == u.Id).SelectStringJoin((m, n) => n.Name, ","),
+                DomainAccount = SqlFunc.Subqueryable<SysUserLdap>().Where(m => m.UserId == u.Id).Select(m => m.Account)
             }, true)
             }, true)
             .ToPagedListAsync(input.Page, input.PageSize);
             .ToPagedListAsync(input.Page, input.PageSize);
     }
     }
@@ -101,7 +105,10 @@ public class SysUserService : IDynamicApiController, ITransient
         var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();
         var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();
         input.Id = newUser.Id;
         input.Id = newUser.Id;
         await UpdateRoleAndExtOrg(input);
         await UpdateRoleAndExtOrg(input);
-
+        if (!string.IsNullOrWhiteSpace(input.DomainAccount))
+        {
+            await _sysUserLdapService.AddUserLdapAsync(newUser.TenantId.Value, newUser.Id, newUser.Account, input.DomainAccount);
+        }
         return newUser.Id;
         return newUser.Id;
     }
     }
 
 
@@ -131,6 +138,7 @@ public class SysUserService : IDynamicApiController, ITransient
         var roleIds = await GetOwnRoleList(input.Id);
         var roleIds = await GetOwnRoleList(input.Id);
         if (input.OrgId != user.OrgId || !input.RoleIdList.OrderBy(u => u).SequenceEqual(roleIds.OrderBy(u => u)))
         if (input.OrgId != user.OrgId || !input.RoleIdList.OrderBy(u => u).SequenceEqual(roleIds.OrderBy(u => u)))
             await _sysOnlineUserService.ForceOffline(input.Id);
             await _sysOnlineUserService.ForceOffline(input.Id);
+        await _sysUserLdapService.AddUserLdapAsync(user.TenantId.Value, user.Id, user.Account, input.DomainAccount);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -171,6 +179,9 @@ public class SysUserService : IDynamicApiController, ITransient
 
 
         // 删除用户扩展机构
         // 删除用户扩展机构
         await _sysUserExtOrgService.DeleteUserExtOrgByUserId(input.Id);
         await _sysUserExtOrgService.DeleteUserExtOrgByUserId(input.Id);
+
+        //删除用户域关联信息
+        await _sysUserLdapService.DeleteUserLdapByUserId(input.Id);
     }
     }
 
 
     /// <summary>
     /// <summary>

+ 84 - 0
Web/src/api-services/apis/sys-ldap-api.ts

@@ -25,6 +25,7 @@ import { AdminResultSysLdap } from '../models';
 import { DeleteSysLdapInput } from '../models';
 import { DeleteSysLdapInput } from '../models';
 import { SysLdapInput } from '../models';
 import { SysLdapInput } from '../models';
 import { UpdateSysLdapInput } from '../models';
 import { UpdateSysLdapInput } from '../models';
+import { UserSyncSysLdapInput } from '../models';
 /**
 /**
  * SysLdapApi - axios parameter creator
  * SysLdapApi - axios parameter creator
  * @export
  * @export
@@ -127,6 +128,54 @@ export const SysLdapApiAxiosParamCreator = function (configuration?: Configurati
                 options: localVarRequestOptions,
                 options: localVarRequestOptions,
             };
             };
         },
         },
+        /**
+         * 
+         * @summary 删除系统域登录信息配置
+         * @param {UserSyncSysLdapInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysLdapUserSyncPost: async (body?: UserSyncSysLdapInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysLdap/userSync`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
         /**
          * 
          * 
          * @summary 获取系统域登录信息配置详情
          * @summary 获取系统域登录信息配置详情
@@ -390,6 +439,20 @@ export const SysLdapApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
                 return axios.request(axiosRequestArgs);
             };
             };
         },
         },
+        /**
+         * 
+         * @summary 同步系统域登录信息配置
+         * @param {UserSyncSysLdapInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysLdapUserSyncPost(body?: UserSyncSysLdapInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysLdapApiAxiosParamCreator(configuration).apiSysLdapUserSyncPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
         /**
          * 
          * 
          * @summary 获取系统域登录信息配置详情
          * @summary 获取系统域登录信息配置详情
@@ -481,6 +544,16 @@ export const SysLdapApiFactory = function (configuration?: Configuration, basePa
         async apiSysLdapDeletePost(body?: DeleteSysLdapInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
         async apiSysLdapDeletePost(body?: DeleteSysLdapInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
             return SysLdapApiFp(configuration).apiSysLdapDeletePost(body, options).then((request) => request(axios, basePath));
             return SysLdapApiFp(configuration).apiSysLdapDeletePost(body, options).then((request) => request(axios, basePath));
         },
         },
+        /**
+         * 
+         * @summary 同步系统域登录信息配置
+         * @param {UserSyncSysLdapInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysLdapUserSyncPost(body?: UserSyncSysLdapInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysLdapApiFp(configuration).apiSysLdapUserSyncPost(body, options).then((request) => request(axios, basePath));
+        },
         /**
         /**
          * 
          * 
          * @summary 获取系统域登录信息配置详情
          * @summary 获取系统域登录信息配置详情
@@ -559,6 +632,17 @@ export class SysLdapApi extends BaseAPI {
     public async apiSysLdapDeletePost(body?: DeleteSysLdapInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
     public async apiSysLdapDeletePost(body?: DeleteSysLdapInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
         return SysLdapApiFp(this.configuration).apiSysLdapDeletePost(body, options).then((request) => request(this.axios, this.basePath));
         return SysLdapApiFp(this.configuration).apiSysLdapDeletePost(body, options).then((request) => request(this.axios, this.basePath));
     }
     }
+    /**
+     * 
+     * @summary 同步系统域登录信息配置
+     * @param {UserSyncSysLdapInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysLdapApi
+     */
+    public async apiSysLdapUserSyncPost(body?: UserSyncSysLdapInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysLdapApiFp(this.configuration).apiSysLdapUserSyncPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
     /**
     /**
      * 
      * 
      * @summary 获取系统域登录信息配置详情
      * @summary 获取系统域登录信息配置详情

+ 8 - 0
Web/src/api-services/models/add-user-input.ts

@@ -311,6 +311,14 @@ export interface AddUserInput {
      */
      */
     jobNum?: string | null;
     jobNum?: string | null;
 
 
+    /**
+     * 域账号
+     *
+     * @type {string}
+     * @memberof UpdateUserInput
+     */
+    domainAccount?: string | null;
+
     /**
     /**
      * 职级
      * 职级
      *
      *

+ 8 - 0
Web/src/api-services/models/sys-user.ts

@@ -326,6 +326,14 @@ export interface SysUser {
      */
      */
     jobNum?: string | null;
     jobNum?: string | null;
 
 
+    /**
+     * 域账号
+     *
+     * @type {string}
+     * @memberof UpdateUserInput
+     */
+    domainAccount?: string | null;
+    
     /**
     /**
      * 职级
      * 职级
      *
      *

+ 8 - 0
Web/src/api-services/models/update-user-input.ts

@@ -311,6 +311,14 @@ export interface UpdateUserInput {
      */
      */
     jobNum?: string | null;
     jobNum?: string | null;
 
 
+    /**
+     * 域账号
+     *
+     * @type {string}
+     * @memberof UpdateUserInput
+     */
+    domainAccount?: string | null;
+    
     /**
     /**
      * 职级
      * 职级
      *
      *

+ 8 - 0
Web/src/api-services/models/user-output.ts

@@ -326,6 +326,14 @@ export interface UserOutput {
      */
      */
     jobNum?: string | null;
     jobNum?: string | null;
 
 
+    /**
+     * 域账号
+     *
+     * @type {string}
+     * @memberof UpdateUserInput
+     */
+    domainAccount?: string | null;
+    
     /**
     /**
      * 职级
      * 职级
      *
      *

+ 30 - 0
Web/src/api-services/models/user-sync-sys-ldap-input.ts

@@ -0,0 +1,30 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+
+ /**
+ * 
+ *
+ * @export
+ * @interface UserSyncSysLdapInput
+ */
+export interface UserSyncSysLdapInput {
+
+    /**
+     * 主键Id
+     *
+     * @type {number}
+     * @memberof UserSyncSysLdapInput
+     */
+    id: number;
+}

+ 16 - 2
Web/src/views/system/ldap/component/editLdap.vue

@@ -16,7 +16,7 @@
 					</el-col>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="端口" prop="port">
 						<el-form-item label="端口" prop="port">
-							<el-input v-model="state.ruleForm.port" type="number" placeholder="请输入端口" clearable />
+							<el-input v-model="state.ruleForm.port" type="number" placeholder="请输入端口" maxlength="5" clearable />
 						</el-form-item>
 						</el-form-item>
 					</el-col>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
@@ -39,9 +39,21 @@
 							<el-input v-model="state.ruleForm.bindPass" placeholder="请输入有域管理权限的密码" maxlength="512" show-word-limit clearable />
 							<el-input v-model="state.ruleForm.bindPass" placeholder="请输入有域管理权限的密码" maxlength="512" show-word-limit clearable />
 						</el-form-item>
 						</el-form-item>
 					</el-col>
 					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="绑定账号属性" prop="bindAttrAccount">
+							<el-input v-model="state.ruleForm.bindAttrAccount" placeholder="请输入域账号字段属性值" maxlength="24"
+								show-word-limit clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="绑定账号属性" prop="bindAttrEmployeeId">
+							<el-input v-model="state.ruleForm.bindAttrEmployeeId" placeholder="请输入绑定用户employeeID属性!"
+								maxlength="24" show-word-limit clearable />
+						</el-form-item>
+					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="Ldap版本" prop="version">
 						<el-form-item label="Ldap版本" prop="version">
-							<el-input v-model="state.ruleForm.version" type="number" placeholder="请输入Ldap版本" clearable />
+							<el-input v-model="state.ruleForm.version" type="number" placeholder="请输入Ldap版本" maxlength="4" clearable />
 						</el-form-item>
 						</el-form-item>
 					</el-col>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
@@ -118,6 +130,8 @@ const rules = ref<FormRules>({
 	bindPass: [{ required: true, message: '请输入绑定密码!', trigger: 'blur' }],
 	bindPass: [{ required: true, message: '请输入绑定密码!', trigger: 'blur' }],
 	authFilter: [{ required: true, message: '请输入用户过滤规则!', trigger: 'blur' }],
 	authFilter: [{ required: true, message: '请输入用户过滤规则!', trigger: 'blur' }],
 	version: [{ required: true, message: '请输入Ldap版本!', trigger: 'blur' }],
 	version: [{ required: true, message: '请输入Ldap版本!', trigger: 'blur' }],
+	bindAttrAccount: [{ required: true, message: '请输入账号绑定字段!', trigger: 'blur', },],
+	bindAttrEmployeeId: [{ required: true, message: '绑定用户employeeID属性!', trigger: 'blur', },],
 });
 });
 
 
 // 导出对象
 // 导出对象

+ 24 - 1
Web/src/views/system/ldap/index.vue

@@ -44,7 +44,15 @@
 				<el-table-column label="操作" width="140" align="center" fixed="right" show-overflow-tooltip="" v-if="auth('sysLdap:update') || auth('sysLdap:delete')">
 				<el-table-column label="操作" width="140" align="center" fixed="right" show-overflow-tooltip="" v-if="auth('sysLdap:update') || auth('sysLdap:delete')">
 					<template #default="scope">
 					<template #default="scope">
 						<el-button icon="ele-Edit" size="small" text="" type="primary" @click="openEditSysLdap(scope.row)" v-auth="'sysLdap:update'"> 编辑 </el-button>
 						<el-button icon="ele-Edit" size="small" text="" type="primary" @click="openEditSysLdap(scope.row)" v-auth="'sysLdap:update'"> 编辑 </el-button>
-						<el-button icon="ele-Delete" size="small" text="" type="danger" @click="delSysLdap(scope.row)" v-auth="'sysLdap:delete'"> 删除 </el-button>
+						<el-dropdown>
+							<el-button icon="ele-MoreFilled" size="small" text type="primary" style="padding-left: 12px" />
+							<template #dropdown>
+								<el-dropdown-menu>
+									<el-dropdown-item icon="ele-OfficeBuilding" @click="syncDomainData(scope.row)" v-auth="'sysLdap:userSync'"> 同步域账户 </el-dropdown-item>
+									<el-dropdown-item icon="ele-Delete" @click="delSysLdap(scope.row)" divided v-auth="'sysLdap:delete'"> 删除角色 </el-dropdown-item>
+								</el-dropdown-menu>
+							</template>
+						</el-dropdown>
 					</template>
 					</template>
 				</el-table-column>
 				</el-table-column>
 			</el-table>
 			</el-table>
@@ -124,6 +132,21 @@ const openEditSysLdap = (row: any) => {
 	editLdapRef.value?.openDialog(row);
 	editLdapRef.value?.openDialog(row);
 };
 };
 
 
+//同步域账户
+const syncDomainData = (row: any) => {
+	ElMessageBox.confirm(`确定要同步吗?`, "提示", {
+		confirmButtonText: "确定",
+		cancelButtonText: "取消",
+		type: "warning",
+	})
+		.then(async () => {
+			await getAPI(SysLdapApi).apiSysLdapUserSyncPost({ id: row.id });
+			handleQuery();
+			ElMessage.success("删除成功");
+		})
+		.catch(() => { });
+};
+
 // 删除
 // 删除
 const delSysLdap = (row: any) => {
 const delSysLdap = (row: any) => {
 	ElMessageBox.confirm(`确定要删除吗:【${row.host}】?`, '提示', {
 	ElMessageBox.confirm(`确定要删除吗:【${row.host}】?`, '提示', {

+ 5 - 0
Web/src/views/system/user/component/editUser.vue

@@ -89,6 +89,11 @@
 									<el-input v-model="state.ruleForm.jobNum" placeholder="工号" clearable />
 									<el-input v-model="state.ruleForm.jobNum" placeholder="工号" clearable />
 								</el-form-item>
 								</el-form-item>
 							</el-col>
 							</el-col>
+							<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+								<el-form-item label="域账号">
+									<el-input v-model="state.ruleForm.domainAccount" placeholder="域账号" clearable />
+								</el-form-item>
+							</el-col>
 							<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 							<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 								<el-form-item label="入职日期">
 								<el-form-item label="入职日期">
 									<el-date-picker v-model="state.ruleForm.joinDate" type="date" placeholder="入职日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" class="w100" />
 									<el-date-picker v-model="state.ruleForm.joinDate" type="date" placeholder="入职日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" class="w100" />