FastGPT如何增减用户

news2024/11/22 17:11:32
背景

开源版本的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"), // 新创建用户的ObjectId
        avatar: "/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"), // 团队的ObjectId
        userId: ObjectId("65916f1a52ac39c5d10bb505"), // 用户的ObjectId
        name: "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 teams
        await MongoTeamMember.deleteMany({ userId: id });

        // Delete teams owned by this user
        const 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 exists
        const 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 password
        const 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 user
        const team = new MongoTeam({
          name: `${username}'s Team`,
          ownerId: savedUser._id,
        });
        const savedTeam = await team.save();

        // Add user to team_members
        const 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.coloradmin.cn/o/2076992.html

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

相关文章

一文带你了解React Hooks

目录 一、useState 二、useRef 三、useEffect 四、自定义Hook 五、Hooks使用规则 Hooks原意是“挂钩”&#xff0c;指将类组件中的部分功能直接可以挂钩到函数组件中&#xff0c;例如state、生命周期方法、副作用等功能。 为什么使用Hooks&#xff1f; 封装代码&#xff…

Harmony鸿蒙应用开发:解决Web组件加载本地资源跨域

鸿蒙开发文档中有一节 加载本地页面 提到了可以通过 $rawfile 方法加载本地 HTML 网页&#xff1a; Index.ets 1Web({ src: $rawfile("local.html"), controller: this.webviewController })但是如果在 local.html 中需要引用一些静态资源&#xff0c;例如图片、JS、…

STM32——TIM定时器的输入捕获功能

一、什么是输出比较与输入捕获&#xff1f; 可以看到&#xff1a; 输出比较OC是用于输出一定频率和占空比的PWM波形&#xff0c;可用于电机驱动进行调速等&#xff1b;而输入捕获IC是用于测量PWM波形的频率以及占空比等参数&#xff1b;和他们的名字相反&#xff0c;一个是比…

Datawhale AI夏令营第四期魔搭- AIGC文生图方向 task01笔记

目录 分任务1&#xff1a;跑通baseline 第一步——搭建代码环境 第二步——报名赛事 第三步——在魔搭社区创建PAI实例 分任务2&#xff1a;相关知识学习以及赛题理解 赛题理解&#xff1a; 文生图基本认识&#xff1a; 1. Diffusion Model(扩散模型) 2. LDMs&#x…

嵌入式Linux学习笔记

1.文件操作命令 2.VI编辑器的部分命令 3.Uboot命令设置环境变量 4. uboot 的顶层 Makefile的重点是“make xxx_defconfig”和“make”这两个命令 &#xff0c;分别如下&#xff1a; 5.在串口SecureCRT中利用uboot启动Linux内核的两种方式 6.Linux内核移植到开发板上也可以反…

常见错误导引 不锈钢螺钉的正确选购和使用分析

紧固件或螺钉是用于固定物体的机械工具。它们用于各种场景&#xff0c;从建造房屋、用具、玩具等。紧固件由多种材料制成&#xff0c;所有这些材料都有特定用途紧固件和用途。一些用于制造螺丝的材料包括不锈钢、铁、铜、铝和塑料。它通常会进行某种表面处理以提高其防锈性和/或…

day-40 合并区间

思路 将二维数组按照第一列升序排列&#xff0c;把intervals[0][0]作为第一个区间的起点&#xff0c;将 intervals[0][1]和intervals[1][0]进行比较&#xff0c;如果intervals[0][1]<intervals[1][0]&#xff0c;则不能合并&#xff0c;否则可以合并&#xff0c;将Math.max(…

绝对不能错过的60个Python日常高频写法总结!

一、 数字 1 求绝对值 绝对值或复数的模 In [1]: abs(-6)Out[1]: 62 进制转化 十进制转换为二进制&#xff1a; In [2]: bin(10)Out[2]: 0b1010十进制转换为八进制&#xff1a; In [3]: oct(9)Out[3]: 0o11十进制转换为十六进制&#xff1a; In [4]: hex(15)Out[4]: 0xf…

[ICS] 物理安全

工业控制系统安全气泡类比 这个理念是&#xff0c;为了防御那些无法更新到最新安全控制措施的旧系统&#xff0c;或者由于设备资源有限而无法处理安全控制措施的系统&#xff0c;帮助可视化这种设备的安全策略可以将它们放置在一个肥皂泡或玻璃泡中。泡中的系统和设备彼此信任…

Spring Cloud Stream与Kafka(一)

Spring Cloud Stream与Kafka&#xff08;一&#xff09; ​ 在实际开发过程中&#xff0c;消息中间件用于解决应用解耦&#xff0c;异步消息&#xff0c;流量削峰等问题&#xff0c;实现高可用、高性能、可伸缩和最终一致性架构。不同的消息中间件实现方式不同&#xff0c;内部…

遥感反演保姆级教程:SPSS筛选因子之后如何采用python建模和反演整个研究区?(以反演生物量为例)

SPSS筛选因子之后如何采用python建模和反演整个研究区?&#xff08;以反演生物量为例&#xff09; 引言 在遥感数据分析中&#xff0c;因子筛选和建模是关键步骤。筛选出与目标变量&#xff08;如生物量&#xff09;显著相关的因子&#xff0c;不仅可以提高模型的预测精度&a…

编程世界的平衡术:日常编码与自我提升的和谐共生

前言 在快速迭代的编程世界中&#xff0c;程序员的角色日益复杂且充满挑战&#xff0c;他们不仅是代码的编织者&#xff0c;更是技术进步的推动者。面对日常编码工作的繁重与个人成长的迫切需求&#xff0c;寻找两者之间的平衡点成为了每位程序员必须深思的问题。以下是我的详细…

C++初学者指南-5.标准库(第二部分)–特殊容器

C初学者指南-5.标准库(第二部分)–特殊容器 pair<A , B> 包含两个相同或不同类型的值 tuple<A , B> C11 包含许多相同或不同类型的值 optional C17 包含一个类型为 T 的值或没有值 variant<A,B,C,…> C17 包含一个类型为A、B或C的值…… any C17 包含任…

《花100块做个摸鱼小网站! 》第四篇—前端应用搭建和完成第一个热搜组件

⭐️基础链接导航⭐️ 服务器 → ☁️ 阿里云活动地址 看样例 → &#x1f41f; 摸鱼小网站地址 学代码 → &#x1f4bb; 源码库地址 一、前言 在本系列文章的早期章节中&#xff0c;我们已经成功地购买了服务器并配置了MySQL、Redis等核心中间件。紧接着&#xff0c;我们不仅…

用AI来学习英语口语(白嫖,所以稍微麻烦些)

写在前面 本文看下如何使用AI来免费学习英语口语。 1&#xff1a;正文 首先&#xff0c;我们点击这里来到一个对话窗口&#xff0c;你可以在这个窗口中使用英语来询问你的问题&#xff0c;比如what can i do when i am not happy&#xff1a; 接着复制机器人回答内容&#…

datawhale AI夏令营第五期 深度学习入门 Task1 了解机器学习

机器学习基础 定义 学习一般是只有人才具备的能力&#xff0c;机器学习就是通过某种方式让机器具备人才有的学习能力&#xff0c;这里的某种方式是机器具备找一个函数的能力 比如说证件照背景颜色更换&#xff0c;那么机器需要找到图片中的背景在哪里&#xff0c;再替换成目…

pandas操作Excel文件

pandas操作Excel文件 一、前言二、指定读取的工作表与header设置2.1指定工作表2.2header设置 三、读取Excel数据3.1iloc读取数据3.2read_excel读取数据3.3loc读取数据 四、DataFrame数据筛选4.1根据列标签对整列进行筛选4.2使用iloc对区域进行筛选4.3自定义筛选 五、DataFrame类…

2024年8月26日(线上考试系统,虚拟化技术部署,使用link)

[rootdocker ~]# systemctl start docker [rootdocker ~]# docker pull mysql 一、线上考试系统 虚拟化技术部署 1、部署前端服务器 project_exam_system.sql数据库文件 dist网络资源 1.将资源上传到服务器 C:\Users\89765>scp -r "D:\青岛实训\project_exam_system\d…

C语言典型例题52

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 题目&#xff1a; 例题4.4 相传古代印度国王舍罕要褒奖他聪明能干的宰相达依尔&#xff08;国际象棋发明者&#xff09;&#xff0c;问他需要什么&#xff0c;达依尔回答说&#xff1a;“国王只要在国际象棋的棋盘的…

Shader 中的渲染顺序

1、深度测试和深度写入 有了深度测试和深度写入发挥作用让我们不需要关心不透明物体的渲染顺序比如一个物体A 挡住了 物体B&#xff0c;即使底层逻辑中 先渲染A&#xff0c;后渲染B&#xff0c;我们也不用担心 B的颜色会把A覆盖&#xff0c;因为在进行深度测试时&#xff0c;远…