FastGPT如何增减用户

背景

开源版本的FastGPT默认只有一个超级用户root,为了更好地管理应用和知识库,可以通过操作MongoDB数据库来增加新的用户和团队。

所需环境
  • 已安装并运行的FastGPT实例
  • MongoDB客户端工具(如Mongo Shell或Robo 3T等)
操作步骤
  1. 启动MongoDB客户端
    在命令行中启动MongoDB客户端,并连接到FastGPT使用的数据库。

  2. 增加新用户
    users集合中插入一条新记录,这条记录包含新用户的详细信息,包括用户名、密码等字段。

    db.getCollection("users").insert({username: "demo",password: "756bc47cb5215dc3329ca7e1f7be33a2dad68990bb94b76d90aa07f4e44a233a", // 请使用安全的方式加密密码status: "active",avatar: "/icon/human.svg",balance: NumberInt("100000"),promotionRate: NumberInt("10"),timezone: "Asia/Shanghai",createTime: new ISODate()
    });
    
  3. 创建新团队
    teams集合中插入一条新记录,这条记录包含团队的基本信息。

    db.getCollection("teams").insert({name: "New Team",ownerId: ObjectId("65916f1a52ac39c5d10bb505"), // 新创建用户的ObjectIdavatar: "/icon/newteam.svg",createTime: new ISODate(),balance: NumberInt("100000"),maxSize: NumberInt("10"),__v: NumberInt("0")
    });
    
  4. 将用户加入团队
    team_members集合中插入一条新记录,这条记录关联了用户和团队。

    db.getCollection("team_members").insert({teamId: ObjectId("65916f3952ac39c5d10bb506"), // 团队的ObjectIduserId: ObjectId("65916f1a52ac39c5d10bb505"), // 用户的ObjectIdname: "Owner",role: "owner",status: "active",createTime: new ISODate(),defaultTeam: true
    });
    
更方便的方式

有了这么多AI,当然可以直接增加管理页面
在这里插入图片描述

  • user.tsx
import React, { useState, useEffect } from 'react';
import {Box,Button,FormControl,FormLabel,Input,VStack,HStack,Table,Thead,Tbody,Tr,Th,Td,Modal,ModalOverlay,ModalContent,ModalHeader,ModalBody,ModalCloseButton,useDisclosure,useToast,Select,
} from '@chakra-ui/react';
import { serviceSideProps } from '@/web/common/utils/i18n';
const fetchUsers = async () => {const response = await fetch('/api/admin/users');if (!response.ok) throw new Error('Failed to fetch users');return response.json();
};const addUser = async (userData) => {const response = await fetch('/api/admin/users', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(userData),});if (!response.ok) throw new Error('Failed to add user');return response.json();
};const updateUser = async (userId, userData) => {const response = await fetch(`/api/admin/users/${userId}`, {method: 'PUT',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(userData),});if (!response.ok) throw new Error('Failed to update user');return response.json();
};const deleteUser = async (userId) => {const response = await fetch(`/api/admin/users/${userId}`, { method: 'DELETE' });if (!response.ok) throw new Error('Failed to delete user');return response.json();
};export default function UserManagement() {const [users, setUsers] = useState([]);const [currentUser, setCurrentUser] = useState(null);const { isOpen, onOpen, onClose } = useDisclosure();const toast = useToast();useEffect(() => {loadUsers();}, []);const loadUsers = async () => {try {const fetchedUsers = await fetchUsers();setUsers(fetchedUsers);} catch (error) {toast({title: "Failed to load users.",description: error.message,status: "error",duration: 3000,isClosable: true,});}};const handleAddUser = async (userData) => {try {const newUser = await addUser(userData);setUsers([...users, newUser.user]);onClose();toast({title: "User added.",status: "success",duration: 2000,isClosable: true,});} catch (error) {toast({title: "Failed to add user.",description: error.message,status: "error",duration: 3000,isClosable: true,});}};const handleUpdateUser = async (userData) => {try {const updatedUser = await updateUser(currentUser._id, userData);setUsers(users.map(user => user._id === updatedUser._id ? updatedUser : user));onClose();toast({title: "User updated.",status: "success",duration: 2000,isClosable: true,});} catch (error) {toast({title: "Failed to update user.",description: error.message,status: "error",duration: 3000,isClosable: true,});}};const handleDeleteUser = async (userId) => {try {await deleteUser(userId);setUsers(users.filter(user => user._id !== userId));toast({title: "User deleted.",status: "success",duration: 2000,isClosable: true,});} catch (error) {toast({title: "Failed to delete user.",description: error.message,status: "error",duration: 3000,isClosable: true,});}};const openAddModal = () => {setCurrentUser(null);onOpen();};const openEditModal = (user) => {setCurrentUser(user);onOpen();};return (<Box p={5}><Button onClick={openAddModal} colorScheme="blue" mb={4}>Add User</Button><Table variant="simple"><Thead><Tr><Th>Username</Th><Th>Status</Th><Th>Balance</Th><Th>Promotion Rate</Th><Th>Timezone</Th><Th>Actions</Th></Tr></Thead><Tbody>{users.map((user) => (<Tr key={user._id}><Td>{user.username}</Td><Td>{user.status}</Td><Td>{user.balance}</Td><Td>{user.promotionRate}%</Td><Td>{user.timezone}</Td><Td><HStack spacing={2}><Button size="sm" onClick={() => openEditModal(user)}>Edit</Button><Button size="sm" colorScheme="red" onClick={() => handleDeleteUser(user._id)}>Delete</Button></HStack></Td></Tr>))}</Tbody></Table><Modal isOpen={isOpen} onClose={onClose}><ModalOverlay /><ModalContent><ModalHeader>{currentUser ? 'Edit User' : 'Add User'}</ModalHeader><ModalCloseButton /><ModalBody><UserForm user={currentUser} onSubmit={currentUser ? handleUpdateUser : handleAddUser} /></ModalBody></ModalContent></Modal></Box>);
}function UserForm({ user, onSubmit }) {const [formData, setFormData] = useState(user || {username: '',password: '',status: 'active',balance: 100000,promotionRate: 10,timezone: 'Asia/Shanghai'});const handleChange = (e) => {const { name, value } = e.target;setFormData({ ...formData, [name]: value });};const handleSubmit = (e) => {e.preventDefault();onSubmit(formData);};return (<form onSubmit={handleSubmit}><VStack spacing={4}><FormControl isRequired><FormLabel>Username</FormLabel><Input name="username" value={formData.username} onChange={handleChange} /></FormControl>{!user && (<FormControl isRequired><FormLabel>Password</FormLabel><Input name="password" type="password" value={formData.password} onChange={handleChange} /></FormControl>)}<FormControl><FormLabel>Status</FormLabel><Select name="status" value={formData.status} onChange={handleChange}><option value="active">Active</option><option value="inactive">Inactive</option></Select></FormControl><FormControl><FormLabel>Balance</FormLabel><Input name="balance" type="number" value={formData.balance} onChange={handleChange} /></FormControl><FormControl><FormLabel>Promotion Rate (%)</FormLabel><Input name="promotionRate" type="number" value={formData.promotionRate} onChange={handleChange} /></FormControl><FormControl><FormLabel>Timezone</FormLabel><Input name="timezone" value={formData.timezone} onChange={handleChange} /></FormControl><Button type="submit" colorScheme="blue">{user ? 'Update' : 'Add'} User</Button></VStack></form>);
}export async function getServerSideProps(content: any) {return {props: {...(await serviceSideProps(content, ['publish', 'user']))}};
}
  • [id].js
import { connectToDatabase } from '@/service/mongo';
import { hashStr } from '@fastgpt/global/common/string/tools';
import { MongoUser } from '@fastgpt/service/support/user/schema';
import { MongoTeam } from '@fastgpt/service/support/user/team/teamSchema';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';export default async function handler(req, res) {const {query: { id },method,} = req;await connectToDatabase();switch (method) {case 'GET':try {const user = await MongoUser.findById(id).select('-password');if (!user) {return res.status(404).json({ error: 'User not found' });}res.status(200).json(user);} catch (error) {res.status(500).json({ error: 'Error fetching user' });}break;case 'PUT':try {const { username, status, avatar, balance, promotionRate, timezone, password } = req.body;const updateDoc = {username,status,avatar,balance,promotionRate,timezone,};if (password) {updateDoc.password = hashStr(password);}const user = await MongoUser.findByIdAndUpdate(id, updateDoc, {new: true,runValidators: true,}).select('-password');if (!user) {return res.status(404).json({ error: 'User not found' });}res.status(200).json(user);} catch (error) {res.status(500).json({ error: 'Error updating user' });}break;case 'DELETE':try {const deletedUser = await MongoUser.findByIdAndDelete(id);if (!deletedUser) {return res.status(404).json({ error: 'User not found' });}// Remove user from teamsawait MongoTeamMember.deleteMany({ userId: id });// Delete teams owned by this userconst ownedTeams = await MongoTeam.find({ ownerId: id });for (const team of ownedTeams) {await MongoTeamMember.deleteMany({ teamId: team._id });await MongoTeam.findByIdAndDelete(team._id);}res.status(200).json({ success: true });} catch (error) {res.status(500).json({ error: 'Error deleting user' });}break;default:res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);res.status(405).end(`Method ${method} Not Allowed`);}
}
  • index.js
// pages/api/users/index.js
import { connectToDatabase } from '@/service/mongo';
import { MongoUser } from '@fastgpt/service/support/user/schema';
import { MongoTeam } from '@fastgpt/service/support/user/team/teamSchema';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { hashStr } from '@fastgpt/global/common/string/tools';
import { authCert } from '@fastgpt/service/support/permission/auth/common';export default async function handler(req, res) {const { method } = req;await connectToDatabase();const { userId } = await authCert({ req, authToken: true });const curUser = await MongoUser.findById(userId).select('-password');if (curUser.username !== 'root') {return res.status(200).json([]);}switch (method) {case 'GET':try {console.log('GET /api/users', MongoUser);const users = await MongoUser.find({ username: { $ne: 'root' } }).select('-password');res.status(200).json(users);} catch (error) {console.log(error);res.status(500).json({ error: 'Error fetching users' });}break;case 'POST':try {const { username, password, status, avatar, balance, promotionRate, timezone } = req.body;// Check if user already existsconst existingUser = await MongoUser.findOne({ username });if (existingUser) {return res.status(400).json({ error: 'Username already exists' });}console.log('POST /api/users', password, hashStr(password), hashStr(hashStr(password)));// Hash passwordconst hashedPassword = hashStr(password);const newUser = new MongoUser({username,password: hashedPassword,status,avatar,balance,promotionRate,timezone,});const savedUser = await newUser.save();// Create a new team for the userconst team = new MongoTeam({name: `${username}'s Team`,ownerId: savedUser._id,});const savedTeam = await team.save();// Add user to team_membersconst teamMember = new MongoTeamMember({teamId: savedTeam._id,userId: savedUser._id,name: 'Owner',role: 'owner',defaultTeam: true,});await teamMember.save();res.status(201).json({ success: true, user: savedUser.toObject({ versionKey: false, transform: (doc, ret) => { delete ret.password; return ret; } }) });} catch (error) {console.log(error);res.status(500).json({ error: 'Error creating user' });}break;default:res.setHeader('Allow', ['GET', 'POST']);res.status(405).end(`Method ${method} Not Allowed`);}
}// pages/api/users/[id].js
  • 访问/admin/user
    在这里插入图片描述

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

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

相关文章

tomcat初步学习

tomcat部署 三太主机 安装 java 环境。两台tomcat-node都安装 安装并启动 tomcat 将之简便处理下放在别的目录并启动 测试 生成 tomcat 的主配置文件 生成启动文件 编辑文件 给与权限后启动 tomcat的反向代理和负载均衡 建立对应文件将之移到目录下 配置后测试 进入文件 写…

用于低质量蒙面人脸识别的一致子决策网络

Consistent Sub-Decision Network for Low-Quality Masked Face Recognition 摘要 提出了一种利用由多个dropout块组成的在线一致性评估结构来获得对应于人脸不同区域的子决策网络&#xff0c;以获得对应于不同面部区域的子决策&#xff0c;并通过加权双向KL散度来约束子决策&…

酒店PMS系统源码之会员系统读取身份证-CyberWinApp-SAAS 本地化及未来之窗行业应用跨平台架构

一、酒店 PMS&#xff08;&#xff09;会员系统 1. 客户关系管理&#xff1a;帮助酒店有效地管理会员信息&#xff0c;包括个人资料、消费记录、偏好等&#xff0c;从而更好地了解会员需求&#xff0c;提供个性化的服务和优惠。 2. 会员忠诚度提升&#xff1a;通过积分、折扣、…

学习C语言(18)

整理今天的学习内容 1.strcmp的使用和模拟实现 strcmp是用来比较字符串的大小的 比较方式&#xff1a;比较两个字符串中对应位置上字符ASCII码值的⼤小 第⼀个字符串大于第二个字符串&#xff0c;则返回⼤于0的数字 第⼀个字符串等于第二个字符串&#xff0c;则返回0 第⼀…

【python计算机视觉编程——3.图像到图像的映射】

python计算机视觉编程——3.图像到图像的映射 3.图像到图像的映射3.1 单应性变换3.1.1 直接线性变换算法&#xff08;DLT&#xff09;3.1.2 仿射变换 3.2 图像扭曲3.2.1 图像中的图像3.2.2 分段仿射扭曲3.2.3 图像配准 3.3 创建全景图3.3.1 RANSAC3.3.2 稳健的单应性矩阵估计3.…

机器学习/数据分析--通俗语言带你入门决策树(结合分类和回归案例)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 机器学习是深度学习和数据分析的基础&#xff0c;接下来将更新常见的机器学习算法注意&#xff1a;在打数学建模比赛中&#xff0c;机器学习用的也很多&a…

从零开始:渗透测试环境安装详细教程

一、引言 在进行渗透测试之前&#xff0c;搭建一个合适的渗透测试环境是至关重要的。一个良好的渗透测试环境可以帮助我们更好地学习和实践渗透测试技术&#xff0c;同时也可以降低对实际生产环境造成的风险。本文将详细介绍如何安装渗透测试环境&#xff0c;包括选择虚拟机软…

李沐--动手学深度学习 批量规范化

1.理论 2.从零开始实现批量规范化 import torch from torch import nn from d2l import torch as d2l from torch.utils.hooks import RemovableHandle #从零开始实现批量规范化 def batch_norm(X,gamma,beta,moving_mean,moving_var,eps,momentum):#通过is_grad_enabled来判断…

PyCharm汉化:简单一步到胃!PyCharm怎么设置中文简体

最近在弄python的项目 一起加油哦 步骤&#xff1a; PyCharm的汉化可以通过两种主要方法完成&#xff1a; 方法一&#xff1a;通过PyCharm内置的插件市场安装中文语言包 1. 打开PyCharm&#xff0c;点击File -> Settings&#xff08;在Mac上是PyCharm -> Preferences…

java一键生成数据库说明文档html格式

要验收项目了&#xff0c;要写数据库文档&#xff0c;一大堆表太费劲了&#xff0c;直接生成一个吧&#xff0c;本来想用个别人的轮子&#xff0c;网上看了几个&#xff0c;感觉效果不怎么好&#xff0c;自己动手写一个吧。抽空再把字典表补充进去就OK了 先看效果&#xff1a; …

Python3:多行文本内容转换为标准的cURL请求参数值

背景 在最近的工作中&#xff0c;经常需要处理一些接口请求的参数&#xff0c;参数来源形式很多&#xff0c;可能是Excel、知识库文档等&#xff0c;有些数据形式比较复杂&#xff0c;比如多行或者包含很多不同的字符&#xff0c;示例如下&#xff1a; **客服质检分析指引** …

【精选】分享9款AI毕业论文生成初稿题目网站

在当今学术研究领域&#xff0c;AI技术的应用日益广泛&#xff0c;尤其是在学术论文的撰写过程中。AI论文生成器的出现&#xff0c;极大地简化了学术写作流程&#xff0c;提高了写作效率。以下是9款推荐的AI毕业论文生成初稿的网站&#xff0c;它们各有特色&#xff0c;能够满足…

MFC工控项目实例之七点击下拉菜单弹出对话框

承接专栏《MFC工控项目实例之六CFile添加菜单栏》 1、在SEAL_PRESSUREDlg.h文件中添加代码 class CSEAL_PRESSUREDlg : public CDialog { ...afx_msg void OnTypeManage(); ... } 2、在SEAL_PRESSUREDlg.cpp文件中添加代码 BEGIN_MESSAGE_MAP(CSEAL_PRESSUREDlg, CDialog)//…

MySQL的源码安装及基本部署(基于RHEL7.9)

这里源码安装mysql的5.7.44版本 一、源码安装 1.下载并解压mysql , 进入目录: wget https://downloads.mysql.com/archives/get/p/23/file/mysql-boost-5.7.44.tar.gz tar xf mysql-boost-5.7.44.tar.gz cd mysql-5.7.44/ 2.准备好mysql编译安装依赖: yum install cmake g…

Python爬虫——简单网页抓取(实战案例)小白篇

Python 爬虫是一种强大的工具&#xff0c;用于从网页中提取数据。这里&#xff0c;我将通过一个简单的实战案例来展示如何使用 Python 和一些流行的库&#xff08;如 requests 和 BeautifulSoup&#xff09;来抓取网页数据。 实战案例&#xff1a;抓取一个新闻网站的头条新闻标…

Windows上传Linux文件行尾符转换

Windows上传Linux文件行尾符转换 1、Windows与Linux文件行尾符2、Windows与Linux文件格式转换 1、Windows与Linux文件行尾符 众所周知&#xff0c;Windows、Mac与Linux三种系统的文件行尾符不同&#xff0c;其中 Windows文件行尾符&#xff08;\r\n&#xff09;&#xff1a; L…

使用kafka改造分布式事务

文章目录 1、kafka确保消息不丢失&#xff1f;1.1、生产者端确保消息不丢失1.2、kafka服务端确保消息不丢失1.3、消费者确保正确无误的消费 2、生产者发送消息 KafkaService3、UserInfoServiceImpl -> login()4、service-account - > AccountListener.java 1、kafka确保消…

day31-测试之性能测试工具JMeter的功能概要、元件作用域和执行顺序

目录 一、JMeter的功能概要 1.1.文件目录介绍 1).bin目录 2).docs目录 3).printable_docs目录 4).lib目录 1.2.基本配置 1).汉化 2).主题修改 1.3.基本使用流程 二、JMeter元件作用域和执行顺序 2.1.名称解释 2.2.基本元件 2.3.元件作用域 1).核心 2).提示 3).作用域的原则 2.…

Redis 实现哨兵模式

目录 1 哨兵模式介绍 1.1 什么是哨兵模式 1.2 sentinel中的三个定时任务 2 配置哨兵 2.1 实验环境 2.2 实现哨兵的三条参数&#xff1a; 2.3 修改配置文件 2.3.1 MASTER 2.3.2 SLAVE 2.4 将 sentinel 进行备份 2.5 开启哨兵模式 2.6 故障模拟 3 在整个架构中可能会出现的问题 …

go中 panicrecoverdefer机制

go的defer机制-CSDN博客 常见panic场景 数组或切片越界&#xff0c;例如 s : make([]int, 3); fmt.Println(s[5]) 会引发 panic: runtime error: index out of range空指针调用&#xff0c;例如 var p *Person; fmt.Println(p.Name) 会引发 panic: runtime error: invalid m…