Dify智能体平台源码二次开发笔记(5) - 多租户的SAAS版实现(2)

目录

前言

用户的查询

controller层

添加路由

service层

用户的添加

controller层

添加路由

service层-添加用户

service层-添加用户和租户关系

验证结果

结果


前言


完成租户添加功能后,下一步需要实现租户下的用户管理。基础功能包括:查询租户用户列表接口,添加用户接口

用户的查询

controller层
class AccountListApi(Resource):"""Resource for getting account list."""@validate_tokendef get(self):"""Get account list."""parser = reqparse.RequestParser()parser.add_argument("tenant_id", type=str, required=True, location="json")parser.add_argument("page", type=int, required=False, default=1, location="args")parser.add_argument("limit", type=int, required=False, default=20, location="args")parser.add_argument("search", type=str, required=False, location="args")args = parser.parse_args()accounts = AccountService.get_accounts_by_tenant(tenant_id=args["tenant_id"],page=args["page"],limit=args["limit"],search=args["search"])return {"result": "success","data": accounts}
添加路由
api.add_resource(AccountListApi, "/accounts")
service层
@staticmethoddef get_accounts_by_tenant(tenant_id: str, page: int = 1, limit: int = 20, search: str = None, status: str = None) -> dict:query = (db.session.query(Account, TenantAccountJoin.role).select_from(Account).join(TenantAccountJoin, Account.id == TenantAccountJoin.account_id).filter(TenantAccountJoin.tenant_id == tenant_id))if search:search = f"%{search}%"query = query.filter(db.or_(Account.name.ilike(search),Account.email.ilike(search)))if status:query = query.filter(Account.status == status)query = query.order_by(Account.name, Account.email)total = query.count()query = query.offset((page - 1) * limit).limit(limit)results = query.all()account_list = [{"id": str(account[0].id),"name": account[0].name,"email": account[0].email,"created_at": account[0].created_at.isoformat(),"role": account[1]} for account in results]return {'items': account_list,'total': total,'page': page,'limit': limit}

用户的添加

controller层
class AccountCreateApi(Resource):"""Resource for creating a new account."""@validate_tokendef post(self):"""Create a new account."""parser = reqparse.RequestParser()parser.add_argument("name", type=str, required=True, location="json")parser.add_argument("email", type=str, required=True, location="json")parser.add_argument("password", type=str, required=True, location="json")parser.add_argument("tenant_id", type=str, required=True, location="json")args = parser.parse_args()account = current_usertenant = TenantService.get_tenant_by_id(args["tenant_id"])if not tenant:return {"result": "fail", "message": "Tenant not found"}, 404try:new_account = AccountService.create_account(email=args["email"],name=args["name"],interface_language="zh-Hans",password=args["password"])TenantService.create_tenant_member(tenant, new_account, role="owner")return {"result": "success","data": {"id": str(new_account.id),"name": new_account.name,"email": new_account.email,"created_at": new_account.created_at.isoformat()}}except Exception as e:return {"result": "error", "message": str(e)}, 400

传入租户id和用户信息,我这里就直接默认语言是中文。

添加路由
api.add_resource(AccountCreateApi, "/accounts/create")
service层-添加用户
@staticmethoddef create_account(email: str,name: str,interface_language: str,password: Optional[str] = None,interface_theme: str = "light",is_setup: Optional[bool] = False,) -> Account:"""create account"""# if not FeatureService.get_system_features().is_allow_register and not is_setup:#     from controllers.console.error import AccountNotFound##     raise AccountNotFound()if dify_config.BILLING_ENABLED and BillingService.is_email_in_freeze(email):raise AccountRegisterError(description=("This email account has been deleted within the past ""30 days and is temporarily unavailable for new account registration"))account = Account()account.email = emailaccount.name = nameif password:# generate password saltsalt = secrets.token_bytes(16)base64_salt = base64.b64encode(salt).decode()# encrypt password with saltpassword_hashed = hash_password(password, salt)base64_password_hashed = base64.b64encode(password_hashed).decode()account.password = base64_password_hashedaccount.password_salt = base64_saltaccount.interface_language = interface_languageaccount.interface_theme = interface_theme# Set timezone based on languageaccount.timezone = language_timezone_mapping.get(interface_language, "UTC")db.session.add(account)db.session.commit()return account
service层-添加用户和租户关系
@staticmethoddef create_tenant_member(tenant: Tenant, account: Account, role: str = "normal") -> TenantAccountJoin:"""Create tenant member"""if role == TenantAccountRole.OWNER.value:if TenantService.has_roles(tenant, [TenantAccountRole.OWNER]):logging.error(f"Tenant {tenant.id} has already an owner.")raise Exception("Tenant already has an owner.")ta = db.session.query(TenantAccountJoin).filter_by(tenant_id=tenant.id, account_id=account.id).first()if ta:ta.role = roleelse:ta = TenantAccountJoin(tenant_id=tenant.id, account_id=account.id, role=role)db.session.add(ta)db.session.commit()return ta

这里直接调用已有方法

TenantAccountJoin
验证结果

用户表

用户租户关联表

结果

用创建的用户和密码从前端登录进去后,智能体、知识库、插件、模型等都完全隔离了。

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

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

相关文章

基于若依的ruoyi-vue-plus的nbmade-boot在线表单的设计(一)架构方面的设计

希望大家一起能参与我的新开源项目nbmade-boot: 宁波智能制造低代码实训平台 主要目标是类似设计jeecgboot那样的online表单功能,因为online本身没有开源这部分代码,而我设计这个是完全开源的,所以希望大家支持支持,开源不容易。 1、数据库方面设计考虑 是在原来gen_table和…

WebFlux应用中获取x-www-form-urlencoded数据的六种方法

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

[Python基础速成]1-Python规范与核心语法

本系列旨在快速掌握Python,实现能够快速阅读和理解 Python 代码,并在可查阅语法的情况下进行 AI 学习。 本篇先了解一下Python基础知识。 本篇内容较菜鸟教程有所删减、方便快速构建大纲,且加入了PEP 8规范说明等有助于理解和编写代码的说明。…

农民剧团的春天与改变之路

杨天义,男,1966年9月生,中共党员,江西省吉安市吉水县水南农民剧团团长。 杨天义从废品收购起家,凭借自身的努力和奋斗,自筹资金100余万元建设了水南镇的第一座影剧院,组建了江西省吉安市吉水县…

python asyncio 的基本使用

1、引言 asyncio 是 Python 标准库中的一个库,提供了对异步 I/O 、事件循环、协程和任务等异步编程模型的支持。 asyncio 文档 2、进程、线程、协程 线程 线程是操作系统调度的基本单位,同一个进程中的多个线程共享相同的内存空间。线程之间的切换由操…

Leedcode刷题 | Day30_贪心算法04

一、学习任务 452. 用最少数量的箭引爆气球代码随想录435. 无重叠区间763. 划分字母区间 二、具体题目 1.452用最少数量的箭引爆气球452. 用最少数量的箭引爆气球 - 力扣(LeetCode) 在二维空间中有许多球形的气球。对于每个气球,提供的输…

Ant Design Vue 表格复杂数据合并单元格

Ant Design Vue 表格复杂数据合并单元格 官方合并效果 官方示例 表头只支持列合并&#xff0c;使用 column 里的 colSpan 进行设置。 表格支持行/列合并&#xff0c;使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时&#xff0c;设置的表格不会渲染。 <temp…

C++ 标准库中的 <algorithm> 头文件算法总结

C 常用 <algorithm> 算法概览 C 标准库中的 <algorithm> 头文件提供了大量有用的算法&#xff0c;主要用于操作容器&#xff08;如 vector, list, array 等&#xff09;。这些算法通常通过迭代器来操作容器元素。 1. 非修改序列操作 std::all_of, std::any_of, s…

程序化广告行业(84/89):4A广告代理公司与行业资质解读

程序化广告行业&#xff08;84/89&#xff09;&#xff1a;4A广告代理公司与行业资质解读 大家好&#xff01;在探索程序化广告行业的道路上&#xff0c;每一次知识的分享都是我们共同进步的阶梯。一直以来&#xff0c;我都希望能和大家携手前行&#xff0c;深入了解这个充满机…

deepin使用autokey添加微信快捷键一键显隐ctrl+alt+w

打开deepin商店&#xff0c;搜索快捷键&#xff0c;找到autokey 快捷键管理&#xff0c;点击安装 点击右键新建文件夹 点击右键新建脚本 打开脚本并添加以下内容 import subprocess import time# ------------------ 配置项 ------------------ WM_CLASS "wechat…

文件内容课堂总结

Spark SQL是Spark用于结构化数据处理的模块&#xff0c;前身是Shark。Shark基于Hive开发&#xff0c;虽提升了SQL-on-Hadoop效率&#xff0c;但对Hive依赖过多。2014年6月1日Shark项目停止开发&#xff0c;团队将资源投入Spark SQL项目。Spark SQL具有诸多优点&#xff0c;如摆…

Zotero PDF Translate 翻译插件使用OpenAI API配置教程

PDF Translate&#xff1a;提升 Zotero 内置 PDF 阅读器的翻译功能 “PDF Translate” 是一款为 Zotero 设计的插件&#xff0c;旨在方便用户在 Zotero 内置的 PDF 阅读器中进行划词或段落翻译&#xff0c;辅助阅读外文文献。 一、 安装插件 下载插件&#xff1a; 访问 PDF T…

火山引擎旗下的产品

用户问的是火山引擎旗下的产品&#xff0c;我需要详细列出各个类别下的产品。首先&#xff0c;我得确认火山引擎有哪些主要业务领域&#xff0c;比如云计算、大数据、人工智能这些。然后&#xff0c;每个领域下具体有哪些产品呢&#xff1f;比如云计算方面可能有云服务器、容器…

C/C++程序中实现Python绑定多种技术路线

在C/C程序中实现Python绑定有多种技术路线&#xff0c;选择合适的方法取决于项目需求、性能要求和开发效率。以下是常见的几种方案&#xff0c;按易用性排序&#xff1a; 1. PyBind11&#xff08;推荐首选&#xff09; 特点&#xff1a;现代C库&#xff0c;语法简洁&#xff0…

【位运算】消失的两个数字

文章目录 面试题 17.19. 消失的两个数字解题思路 面试题 17.19. 消失的两个数字 面试题 17.19. 消失的两个数字 ​ 给定一个数组&#xff0c;包含从 1 到 N 所有的整数&#xff0c;但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗&#xff1f; ​ 以任意…

自然语言处理Hugging Face Transformers

Hugging Face Transformers 是一个基于 PyTorch 和 TensorFlow 的开源库&#xff0c;专注于 最先进的自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;如 BERT、GPT、RoBERTa、T5 等。它提供了 预训练模型、微调工具和推理 API&#xff0c;广泛应用于文本分类、机器翻…

vue开发基础流程 (后20)

创建项目命令&#xff1b; 或者 vue create my - vue - router - project这个是创建带路由的项目 22.组件组成 比如说一个页面吧&#xff0c;他三个组件&#xff0c;template就是用来放所有的标签&#xff0c;script用来放业务逻辑&#xff0c;style用来放样式&#xff0c;c…

高性能内存kv数据库Redis

引言 在当今数据驱动的时代&#xff0c;高效的数据存储和检索对于各类应用程序至关重要。Redis&#xff08;Remote Dictionary Server&#xff09;作为一款开源的内存键值数据库&#xff0c;凭借其出色的性能、丰富的数据结构和灵活的特性&#xff0c;在众多场景中得到了广泛应…

自动化测试概念篇

文章目录 目录1. 自动化1.1 自动化概念1.1.1 回归测试 1.2 自动化分类1.3 自动化测试金字塔 2. web自动化测试2.1 驱动2.1.1 安装驱动管理2.1.2 selenium库 3. Selenium3.1 一个简单的web自动化示例3.2 selenium驱动浏览器的工作原理 目录 自动化web自动化测试Selenium 1. 自…

《AI大模型应知应会100篇》第17篇:大模型的偏见与公平性问题

第17篇&#xff1a;大模型的偏见与公平性问题 摘要 在人工智能迅速发展的今天&#xff0c;大型语言模型&#xff08;LLM&#xff09;已经深入到我们的日常生活和工作中。然而&#xff0c;这些模型并非完美无缺&#xff0c;它们可能携带并放大数据中的偏见&#xff0c;导致不公…