怎样优雅地增删查改(二):扩展身份管理模块

news2024/9/22 12:21:53

文章目录

    • 用户关系管理
    • 扩展组织管理功能
      • 创建可查询仓储
    • 实现控制器
    • 测试接口

身份管理模块(Identity模块)为通用查询接口的按组织架构查询和按户关系查询提供查询依据。

身份管理模块的领域层依赖Volo.Abp.Identity.Domain

在这里插入图片描述

Abp为我们实现了一套身份管理模块,此模块包含用户管理、角色管理、组织管理、权限管理等功能。详细请参考身份管理模块。

我们将基于Volo.Abp.Identity模块按需求扩展。将为其扩展组织管理功能的接口,以及人员关系(Relation)功能。

用户关系管理

Relation是人员之间的关系,比如:签约、关注,或者朋友关系等。人员之间的关系是单项的,也就是说可以A是B的好友,但B不一定是A的好友。

关系类型由Type来定义

正向关系:User -> RelatedUser,由查询GetRelatedToUsersAsync实现;

反向关系:RelatedUser -> User,由查询GetRelatedFromUsersAsync实现。

添加Relation实体:

public class Relation : FullAuditedAggregateRoot<long>
{
    public Guid? TenantId { get; set; }

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public override long Id { get; protected set; }

    public Guid UserId { get; set; }

    [ForeignKey("UserId")]
    public IdentityUser User { get; set; }

    public Guid RelatedUserId { get; set; }

    [ForeignKey("RelatedUserId")]
    public IdentityUser RelatedUser { get; set; }

    public string Type { get; set; }

}

在模块配置中添加

public class IdentityEntityFrameworkCoreModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.AddAbpDbContext<IdentityDbContext>(options =>
        {
            options.AddRepository<IdentityUserOrganizationUnit, EfCoreRepository<IdentityDbContext, IdentityUserOrganizationUnit>>();
            options.AddRepository<Relation.Relation, EfCoreRepository<IdentityDbContext, Relation.Relation>>();
        });
    }
}

创建RelationManager,实现人员关系的正向和反向查询

public async Task<List<Relation>> GetRelatedToUsersAsync(Guid userId, string type)
{
    var query = (await Repository.GetQueryableAsync())
        .WhereIf(userId != null, c => userId == c.UserId)
        .WhereIf(!string.IsNullOrEmpty(type), c => c.Type == type);
    var items = query.ToList();
    return items;

}

public async Task<List<Relation>> GetRelatedFromUsersAsync(Guid userId, string type)
{
    var query = (await Repository.GetQueryableAsync())
        .Where(c => userId == c.RelatedUserId)
        .WhereIf(!string.IsNullOrEmpty(type), c => c.Type == type);
    var items = query.ToList();
    return items;
}

扩展组织管理功能

组织(OrganizationUnit)是身份管理模块的核心概念,组织是树形结构,组织之间存在父子关系。

我们对功能模块的接口进行扩展:

  1. 增加OrganizationUnit的增删查改接口;

  2. 增加OrganizationUnit的移动接口;

  3. 增加人员与组织架构管理接口,如添加/删除人员到组织架构,查询组织架构下的人员,查询未分配组织的人员等;

  4. 增加查询根组织(GetRootOrganizationUnit)接口。

完整的应用层接口如下:

public interface IOrganizationUnitAppService : IBasicCurdAppService<OrganizationUnitDto, Guid, CreateOrganizationUnitInput, UpdateOrganizationUnitInput>, IApplicationService
{
    Task AddToOrganizationUnitAsync(UserToOrganizationUnitInput input);
    Task<List<OrganizationUnitDto>> GetCurrentOrganizationUnitsAsync();
    Task<PagedResultDto<IdentityUserDto>> GetOrganizationUnitUsersByPageAsync(GetOrganizationUnitUsersInput input);
    Task<List<IdentityUserDto>> GetOrganizationUnitUsersAsync(GetOrganizationUnitUsersInput input);
    Task<OrganizationUnitDto> GetRootOrganizationUnitAsync(Guid id);
    Task<List<OrganizationUnitDto>> GetRootOrganizationUnitsAsync(IEnumerable<Guid> ids);
    Task<OrganizationUnitDto> GetRootOrganizationUnitByDisplayNameAsync(GetRootOrganizationUnitByDisplayName input);
    Task<List<OrganizationUnitDto>> GetRootOrganizationUnitsByParentAsync(GetRootOrganizationUnitsByParentInput input);
    Task<bool> IsInOrganizationUnitAsync(UserToOrganizationUnitInput input);
    Task MoveOrganizationUnitAsync(MoveOrganizationUnitInput input);
    Task RemoveUserFromOrganizationUnitAsync(UserToOrganizationUnitInput input);
    Task<List<IdentityUserDto>> GetUsersWithoutOrganizationAsync(GetUserWithoutOrganizationInput input);
    Task<PagedResultDto<IdentityUserDto>> GetUsersWithoutOrganizationByPageAsync(GetUserWithoutOrganizationInput input);
}

创建可查询仓储

通用查询接口过滤条件需要对IQueryable进行拼接,由于Volo.Abp.Identity.IIdentityUserRepository继承自IBasicRepository,我们需要重新编写一个IdentityUser的可查询仓储:QueryableIdentityUserRepository

其实现接口IQueryableIdentityUserRepository的定义如下:

public interface IQueryableIdentityUserRepository : IIdentityUserRepository
{
    Task<IQueryable<OrganizationUnit>> GetOrganizationUnitsQueryableAsync(Guid id, bool includeDetails = false);
    Task<IQueryable<IdentityUser>> GetOrganizationUnitUsersAsync(
        Guid id, string keyword, string[] type,
        bool includeDetails = false);
    Task<IQueryable<IdentityUser>> GetUsersWithoutOrganizationAsync(string keyword, string[] type);
}

实现控制器

为OrganizationUnitAppService 以及 RelationAppService 创建MVC控制器

完整的 OrganizationUnitController 代码如下:

namespace Matoapp.Identity.OrganizationUnit
{
    [Area(IdentityRemoteServiceConsts.ModuleName)]
    [RemoteService(Name = IdentityRemoteServiceConsts.RemoteServiceName)]
    [Route("api/identity/organizationUnit")]
    public class OrganizationUnitController : IdentityController, IOrganizationUnitAppService
    {
        private readonly IOrganizationUnitAppService _organizationUnitAppService;

        public OrganizationUnitController(IOrganizationUnitAppService organizationUnitAppService)
        {
            _organizationUnitAppService = organizationUnitAppService;
        }

        [HttpPost]
        [Route("AddToOrganizationUnit")]
        
        public async Task AddToOrganizationUnitAsync(UserToOrganizationUnitInput input)
        {
            await _organizationUnitAppService.AddToOrganizationUnitAsync(input);
        }

        [HttpPost]
        [Route("Create")]
        
        public async Task<OrganizationUnitDto> CreateAsync(CreateOrganizationUnitInput input)
        {
            return await _organizationUnitAppService.CreateAsync(input);
        }

        [HttpDelete]
        [Route("Delete")]
        
        public async Task DeleteAsync(Guid id)
        {
            await _organizationUnitAppService.DeleteAsync(id);
        }


        [HttpGet]
        [Route("Get")]
        
        public async Task<OrganizationUnitDto> GetAsync(Guid id)
        {
            return await _organizationUnitAppService.GetAsync(id);

        }

        [HttpGet]
        [Route("GetCurrentOrganizationUnits")]

        
        public async Task<List<OrganizationUnitDto>> GetCurrentOrganizationUnitsAsync()
        {
            return await _organizationUnitAppService.GetCurrentOrganizationUnitsAsync();
        }


        [HttpGet]
        [Route("GetOrganizationUnitUsers")]
        
        public async Task<List<IdentityUserDto>> GetOrganizationUnitUsersAsync(GetOrganizationUnitUsersInput input)
        {
            return await _organizationUnitAppService.GetOrganizationUnitUsersAsync(input);
        }

        [HttpGet]
        [Route("GetOrganizationUnitUsersByPage")]
        
        public async Task<PagedResultDto<IdentityUserDto>> GetOrganizationUnitUsersByPageAsync(GetOrganizationUnitUsersInput input)
        {
            return await _organizationUnitAppService.GetOrganizationUnitUsersByPageAsync(input);
        }

        [HttpGet]
        [Route("GetRootOrganizationUnit")]
        
        public async Task<OrganizationUnitDto> GetRootOrganizationUnitAsync(Guid id)
        {
            return await _organizationUnitAppService.GetRootOrganizationUnitAsync(id);
        }

        [HttpGet]
        [Route("GetRootOrganizationUnits")]
        
        public async Task<List<OrganizationUnitDto>> GetRootOrganizationUnitsAsync(IEnumerable<Guid> ids)
        {
            return await _organizationUnitAppService.GetRootOrganizationUnitsAsync(ids);
        }

        [HttpGet]
        [Route("GetRootOrganizationUnitByDisplayName")]
        
        public async Task<OrganizationUnitDto> GetRootOrganizationUnitByDisplayNameAsync(GetRootOrganizationUnitByDisplayName input)
        {
            return await _organizationUnitAppService.GetRootOrganizationUnitByDisplayNameAsync(input);
        }

        [HttpGet]
        [Route("GetRootOrganizationUnitsByParent")]
        
        public async Task<List<OrganizationUnitDto>> GetRootOrganizationUnitsByParentAsync(GetRootOrganizationUnitsByParentInput input)
        {
            return await _organizationUnitAppService.GetRootOrganizationUnitsByParentAsync(input);
        }

        [HttpGet]
        [Route("GetUsersWithoutOrganization")]
        
        public async Task<List<IdentityUserDto>> GetUsersWithoutOrganizationAsync(GetUserWithoutOrganizationInput input)
        {
            return await _organizationUnitAppService.GetUsersWithoutOrganizationAsync(input);
        }

        [HttpGet]
        [Route("GetUsersWithoutOrganizationByPage")]
        
        public async Task<PagedResultDto<IdentityUserDto>> GetUsersWithoutOrganizationByPageAsync(GetUserWithoutOrganizationInput input)
        {
            return await _organizationUnitAppService.GetUsersWithoutOrganizationByPageAsync(input);
        }

        [HttpGet]
        [Route("IsInOrganizationUnit")]
        
        public async Task<bool> IsInOrganizationUnitAsync(UserToOrganizationUnitInput input)
        {
            return await _organizationUnitAppService.IsInOrganizationUnitAsync(input);
        }

        [HttpPost]
        [Route("MoveOrganizationUnit")]
        
        public async Task MoveOrganizationUnitAsync(MoveOrganizationUnitInput input)
        {
            await _organizationUnitAppService.MoveOrganizationUnitAsync(input);
        }

        [HttpPost]
        [Route("RemoveUserFromOrganizationUnit")]
        
        public async Task RemoveUserFromOrganizationUnitAsync(UserToOrganizationUnitInput input)
        {
            await _organizationUnitAppService.RemoveUserFromOrganizationUnitAsync(input);
        }

        [HttpPut]
        [Route("Update")]
        
        public async Task<OrganizationUnitDto> UpdateAsync(UpdateOrganizationUnitInput input)
        {
            return await _organizationUnitAppService.UpdateAsync(input);
        }

    }

完整的 RelationController 代码如下:

    [Area(IdentityRemoteServiceConsts.ModuleName)]
    [RemoteService(Name = IdentityRemoteServiceConsts.RemoteServiceName)]
    [Route("api/identity/relation")]
    public class RelationController : IdentityController, IRelationAppService
    {
        private readonly IRelationAppService _relationAppService;

        public RelationController(IRelationAppService relationAppService)
        {
            _relationAppService = relationAppService;
        }

        [HttpDelete]
        [Route("ClearAllRelatedFromUsers")]

        public async Task ClearAllRelatedFromUsersAsync(GetRelatedUsersInput input)
        {
            await _relationAppService.ClearAllRelatedFromUsersAsync(input);
        }

        [HttpDelete]
        [Route("ClearAllRelatedToUsers")]

        public async Task ClearAllRelatedToUsersAsync(GetRelatedUsersInput input)
        {
            await _relationAppService.ClearAllRelatedToUsersAsync(input);
        }

        [HttpPost]
        [Route("Create")]

        public async Task<RelationDto> CreateAsync(ModifyRelationInput input)
        {
            return await _relationAppService.CreateAsync(input);
        }

        [HttpDelete]
        [Route("Delete")]

        public async Task DeleteAsync(EntityDto<long> input)
        {
            await _relationAppService.DeleteAsync(input);
        }

        [HttpDelete]
        [Route("DeleteByUserId")]

        public async Task DeleteByUserIdAsync(ModifyRelationInput input)
        {
            await _relationAppService.DeleteByUserIdAsync(input);
        }

        [HttpGet]
        [Route("GetRelatedFromUsers")]

        public async Task<List<IdentityUserDto>> GetRelatedFromUsersAsync(GetRelatedUsersInput input)
        {
            return await _relationAppService.GetRelatedFromUsersAsync(input);
        }

        [HttpGet]
        [Route("GetRelatedToUsers")]

        public async Task<List<IdentityUserDto>> GetRelatedToUsersAsync(GetRelatedUsersInput input)
        {
            return await _relationAppService.GetRelatedToUsersAsync(input);
        }

        [HttpGet]
        [Route("GetRelatedToUserIds")]
        public async Task<List<Guid>> GetRelatedToUserIdsAsync(GetRelatedUsersInput input)
        {
            return await _relationAppService.GetRelatedToUserIdsAsync(input);
        }


        [HttpGet]
        [Route("GetRelatedFromUserIds")]
        public async Task<List<Guid>> GetRelatedFromUserIdsAsync(GetRelatedUsersInput input)
        {
            return await _relationAppService.GetRelatedFromUserIdsAsync(input);
        }


    }

测试接口

上一章节我们已经将三个模组的依赖添加到MatoappHttpApiModule中,直接启动HttpApi.Host就可以访问接口了。

[DependsOn(
    ...
    typeof(CommonHttpApiModule),
    typeof(HealthHttpApiModule),
    typeof(IdentityHttpApiModule)
    )]
public class MatoappHttpApiModule : AbpModule

Relation相关接口:

在这里插入图片描述

OrganizationUnit相关接口:

在这里插入图片描述

下一章节将介绍如何利用Identity模块为用户的查询提供组织架构和用户关系的条件过滤。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728374.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CentOS 7镜像下载 以及 DVD ISO 和 Minimal ISO 等各版本的区别介绍

1.官网下载 官网下载地址&#xff1a;官网下载链接 点击进入下载页面&#xff0c;随便选择一个下载即可&#xff08;不推荐&#xff0c;推荐阿里云下载&#xff0c;见下文&#xff09; 阿里云下载站点&#xff08;速度非常快推荐&#xff09; 阿里云下载链接&#xff1a; http…

免费下载!10个3D素材网站推荐

在设计工作中&#xff0c;3D素材可以帮助设计师创建高质量的UI设计&#xff0c;提高设计效率和准确性。本文将为您推荐10个好用的3D素材网站&#xff0c;助力设计师实现高效创作。 1.即时设计资源广场 即时设计资源广场是一个致力于为设计师提供丰富多样的设计资产和灵感的社…

chatgpt 与传统3D建模对比分析

推荐&#xff1a;将NSDT场景编辑器加入你的3D工具链 随着人工智能技术的发展&#xff0c;越来越多的领域正逐渐被AI模型所取代。ChatGPT作为一种自然语言处理技术&#xff0c;越来越为人们所熟悉。最近&#xff0c;一些3D建模领域的专家想知道ChatGPT是否可以取代传统的手动3D建…

ClickHouse主键索引最佳实践

在本文中&#xff0c;我们将深入研究ClickHouse索引。我们将对此进行详细说明和讨论&#xff1a; ClickHouse的索引与传统的关系数据库有何不同ClickHouse是怎样构建和使用主键稀疏索引的ClickHouse索引的最佳实践 您可以选择在自己的机器上执行本文给出的所有Clickhouse SQL…

C++之Clang属性大全(一百五十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

NC65自由报表参数设置后,报表发布成节点后,点击查询,在查询框输入条件后,参数值没有拼接到sql中的解决方法

NC65自由报表参数设置后&#xff0c;报表发布成节点后&#xff0c;点击查询&#xff0c;在查询框输入条件后&#xff0c;参数值没有拼接到sql中的解决方法 在语义分析模型中把sql语句放进去&#xff0c;把字段和查询查询设置好 语义模型的sql使用了parameter把参数输入 sel…

eNSP-OSPF组播拓展复杂区域连接

OSPF动态路由 文章目录 OSPF动态路由一、题目要求二、题目分析三、拓扑结构四、基础配置五、测试验证 一、题目要求 1 、 使用172.16.0.0.0/16网段进行子网划分 2 、 用OSPF协议达到全网可达 3 、 保证所有设备均具备最少的 LSDB 以及路由表 二、题目分析 1.网段划分 5个O…

将OxyPlot封装成用户控件后在WPF中的应用

1、文件架构 2、加载依赖项 Newtonsoft.Json OxyPlot.Wpf 3、NotifyBase.cs namespace Accurate.Common {public class NotifyBase : INotifyPropertyChanged{public event PropertyChangedEventHandler? PropertyChanged;public void DoNotify([CallerMemberName] string p…

【深度学习】日常笔记10

loss_fn nn.MSELoss(reductionnone)这行代码&#xff0c;在这个上下文中&#xff0c;loss_fn实际上是一个损失函数对象而不是返回的具体值。 使用nn.MSELoss(reductionnone)创建的loss_fn是一个均方误差损失函数对象&#xff0c;而不是计算后的结果。要计算具体的损失值&…

(02)Cartographer源码无死角解析-(79) ROS服务→子图压缩与服务发送

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文…

一篇文章带你吃透Go语言的Atomic和Channel--实战方法

一篇文章带你吃透Go语言的Atomic和Channel–实战方法 Atomic 要保证原子操作&#xff0c;一定要使用这几种方法 我们在学习 Mutex、RWMutex 等并发原语的实现时&#xff0c;你可以看到&#xff0c;最底层是通过 atomic 包中的一些原子操作来实现的 你可能会说&#xff0c;这些…

C语言中级篇请看另一篇文章,这一篇文章只写给高手看【高阶C语言】【更新中】【原创】

文章目录 前言define和typedef的区别?前言 关于C语言,博主已经写了不少的笔记总结了,C语言基础版可看我的专栏里面的C语言精华,C语言进阶版可看我的谭浩强C语言第五版,C语言高阶版看此篇文章即可 C Primer Plus书籍,C语言精华,截图 + 代码 + 学习总结笔记【11000字】【…

AOCVSBOCV、AOCV table

文章目录 AOCV&#xff08;Advanced OCV&#xff09;&SBOCV&#xff08;Stage Based OCV&#xff09;---更精确&#xff0c;剔除悲观度Random variation&#xff08;Depth/Stage based AOCV&#xff09;Systematic variation&#xff08;Distance based AOCV&#xff09;一…

阻塞队列是什么

1、阻塞队列是什么? (1) 栈与队列 1&#xff09;栈&#xff1a;先进后出&#xff0c;后进先出 2&#xff09;队列&#xff1a;先进先出 (2) 阻塞队列 阻塞&#xff1a;必须要阻塞/不得不阻塞 阻塞队列是一个队列&#xff0c;在数据结构中起的作用如下图&#xff1a; 线程1…

直播美颜工具与实时美颜SDK开发指南

近年来&#xff0c;随着直播行业的蓬勃发展&#xff0c;越来越多的用户开始关注直播内容的质量。其中&#xff0c;美颜功能成为直播平台上不可或缺的一项特色功能。下文小编将从基础原理到实际应用&#xff0c;帮助开发者更好地实现高效又自然的美颜效果。 一、背景 在直播过…

spring之ApplicationContext

spring之ApplicationContext ApplicationContextApplicationContext源码ApplicationContext继承接口分析ApplicationContext两个比较重要的实现类AnnotationConfigApplicationContextClassPathXmlApplicationContext 国际化---MessageSource资源加载---ResourceLoader获取运行时…

多元回归预测 | Matlab鲸鱼算法(WOA)优化极限梯度提升树XGBoost回归预测,WOA-XGBoost回归预测模型,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab鲸鱼算法(WOA)优化极限梯度提升树XGBoost回归预测,WOA-XGBoost回归预测模型,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源…

css实现九宫格有边框,最外层四周无边框

1.先设置9个div&#xff0c;如下&#xff1a; <div class"wrapper"><div class"cell"></div><div class"cell"></div><div class"cell"></div><div class"cell"></div&…

【MySQL】连接 MySQL使用二进制方式连接和脚本连接,修改密码,增加新用户,显示命令

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

RocketMQ5.0--消息发送

RocketMQ5.0–消息发送 一、消息 // 消息所属topic private String topic; // 消息Flag&#xff08;RocketMQ不作处理&#xff09;&#xff0c;即&#xff1a;用户处理 private int flag; // 扩展属性 private Map<String, String> properties; // 消息体 private byte…