mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
feat: admin add user
This commit is contained in:
@@ -25,7 +25,7 @@
|
|||||||
"react-admin": "^4.11.0",
|
"react-admin": "^4.11.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-i18next": "^12.3.1",
|
"react-i18next": "^12.3.1",
|
||||||
"tushan": "^0.2.30"
|
"tushan": "^0.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jsonexport": "^3.0.2",
|
"@types/jsonexport": "^3.0.2",
|
||||||
|
3521
admin/pnpm-lock.yaml
generated
3521
admin/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -16,14 +16,21 @@ useKbRoute(app);
|
|||||||
useSystemRoute(app);
|
useSystemRoute(app);
|
||||||
|
|
||||||
app.get('/*', (req, res) => {
|
app.get('/*', (req, res) => {
|
||||||
res.sendFile(new URL('dist/index.html', import.meta.url).pathname);
|
try {
|
||||||
|
res.sendFile(new URL('dist/index.html', import.meta.url).pathname);
|
||||||
|
} catch (error) {
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use((err, req, res, next) => {
|
app.use((err, req, res, next) => {
|
||||||
res.sendFile(new URL('dist/index.html', import.meta.url).pathname);
|
try {
|
||||||
|
res.sendFile(new URL('dist/index.html', import.meta.url).pathname);
|
||||||
|
} catch (error) {
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const PORT = process.env.PORT || 3001;
|
const PORT = process.env.PORT || 3001;
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Server is running on port ${PORT}`);
|
console.log(`Server is running on port ${PORT}`);
|
||||||
|
@@ -46,63 +46,6 @@ export const useSystemRoute = (app) => {
|
|||||||
res.status(401).end('username or password incorrect');
|
res.status(401).end('username or password incorrect');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
app.get('/system', auth(), async (req, res) => {
|
|
||||||
try {
|
|
||||||
const data = await System.find();
|
|
||||||
const totalCount = await System.countDocuments();
|
|
||||||
|
|
||||||
res.header('Access-Control-Expose-Headers', 'X-Total-Count');
|
|
||||||
res.header('X-Total-Count', totalCount);
|
|
||||||
res.json(
|
|
||||||
data.map((item) => {
|
|
||||||
const obj = item.toObject();
|
|
||||||
return {
|
|
||||||
...obj,
|
|
||||||
id: obj._id
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
|
|
||||||
res.status(500).json({ error: 'Error creating system env' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
app.post('/system', auth(), async (req, res) => {
|
|
||||||
try {
|
|
||||||
await System.create({
|
|
||||||
...req.body,
|
|
||||||
sensitiveCheck: req.body.sensitiveCheck === 'true'
|
|
||||||
});
|
|
||||||
postParent();
|
|
||||||
res.json({});
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ error: 'Error creating system env' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
app.put('/system/:id', auth(), async (req, res) => {
|
|
||||||
try {
|
|
||||||
const _id = req.params.id;
|
|
||||||
await System.findByIdAndUpdate(_id, {
|
|
||||||
...req.body,
|
|
||||||
sensitiveCheck: req.body.sensitiveCheck === 'true'
|
|
||||||
});
|
|
||||||
postParent();
|
|
||||||
res.json({});
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ error: 'Error updating system env' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
app.delete('/system/:id', auth(), async (req, res) => {
|
|
||||||
try {
|
|
||||||
const _id = req.params.id;
|
|
||||||
await System.findByIdAndDelete(_id);
|
|
||||||
|
|
||||||
res.json({});
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ error: 'Error updating system env' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const auth = () => {
|
export const auth = () => {
|
||||||
@@ -110,7 +53,7 @@ export const auth = () => {
|
|||||||
try {
|
try {
|
||||||
const authorization = req.headers.authorization;
|
const authorization = req.headers.authorization;
|
||||||
if (!authorization) {
|
if (!authorization) {
|
||||||
return next(new Error("unAuthorization"))
|
return next(new Error('unAuthorization'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = authorization.slice('Bearer '.length);
|
const token = authorization.slice('Bearer '.length);
|
||||||
|
@@ -2,6 +2,11 @@ import { User, Pay } from '../schema.js';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { auth } from './system.js';
|
import { auth } from './system.js';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
export const PRICE_SCALE = 100000;
|
||||||
|
|
||||||
|
export const formatPrice = (val = 0, multiple = 1) => {
|
||||||
|
return Number(((val / PRICE_SCALE) * multiple).toFixed(10));
|
||||||
|
};
|
||||||
|
|
||||||
// 加密
|
// 加密
|
||||||
const hashPassword = (psw) => {
|
const hashPassword = (psw) => {
|
||||||
@@ -78,6 +83,7 @@ export const useUserRoute = (app) => {
|
|||||||
return {
|
return {
|
||||||
...obj,
|
...obj,
|
||||||
id: obj._id,
|
id: obj._id,
|
||||||
|
balance: formatPrice(obj.balance),
|
||||||
createTime: dayjs(obj.createTime).format('YYYY/MM/DD HH:mm'),
|
createTime: dayjs(obj.createTime).format('YYYY/MM/DD HH:mm'),
|
||||||
password: ''
|
password: ''
|
||||||
};
|
};
|
||||||
@@ -107,8 +113,8 @@ export const useUserRoute = (app) => {
|
|||||||
|
|
||||||
const result = await User.create({
|
const result = await User.create({
|
||||||
username,
|
username,
|
||||||
password,
|
password: hashPassword(hashPassword(password)),
|
||||||
balance
|
balance: balance * PRICE_SCALE
|
||||||
});
|
});
|
||||||
res.json(result);
|
res.json(result);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -116,17 +122,17 @@ export const useUserRoute = (app) => {
|
|||||||
res.status(500).json({ error: 'Error creating user' });
|
res.status(500).json({ error: 'Error creating user' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 修改用户信息
|
// 修改用户信息
|
||||||
app.put('/users/:id', auth(), async (req, res) => {
|
app.put('/users/:id', auth(), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const _id = req.params.id;
|
const _id = req.params.id;
|
||||||
|
|
||||||
let { password, balance = 0 } = req.body;
|
let { username, password, balance = 0 } = req.body;
|
||||||
|
|
||||||
const result = await User.findByIdAndUpdate(_id, {
|
const result = await User.findByIdAndUpdate(_id, {
|
||||||
|
...(username && { username }),
|
||||||
...(password && { password: hashPassword(hashPassword(password)) }),
|
...(password && { password: hashPassword(hashPassword(password)) }),
|
||||||
...(balance && { balance })
|
...(balance && { balance: balance * PRICE_SCALE })
|
||||||
});
|
});
|
||||||
res.json(result);
|
res.json(result);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -134,6 +140,7 @@ export const useUserRoute = (app) => {
|
|||||||
res.status(500).json({ error: 'Error updating user' });
|
res.status(500).json({ error: 'Error updating user' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 新增: 获取 pays 列表
|
// 新增: 获取 pays 列表
|
||||||
app.get('/pays', auth(), async (req, res) => {
|
app.get('/pays', auth(), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
@@ -21,22 +21,39 @@ mongoose
|
|||||||
.then(() => console.log('Connected to MongoDB successfully!'))
|
.then(() => console.log('Connected to MongoDB successfully!'))
|
||||||
.catch((err) => console.log(`Error connecting to MongoDB: ${err}`));
|
.catch((err) => console.log(`Error connecting to MongoDB: ${err}`));
|
||||||
|
|
||||||
const userSchema = new mongoose.Schema({
|
const UserSchema = new mongoose.Schema({
|
||||||
_id: mongoose.Schema.Types.ObjectId,
|
username: {
|
||||||
username: String,
|
type: String,
|
||||||
password: String,
|
required: true,
|
||||||
balance: Number,
|
unique: true
|
||||||
promotion: {
|
|
||||||
rate: Number
|
|
||||||
},
|
},
|
||||||
openaiKey: String,
|
password: {
|
||||||
avatar: String,
|
type: String,
|
||||||
createTime: Date
|
required: true,
|
||||||
|
select: false
|
||||||
|
},
|
||||||
|
createTime: {
|
||||||
|
type: Date,
|
||||||
|
default: () => new Date()
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
type: String,
|
||||||
|
default: '/icon/human.png'
|
||||||
|
},
|
||||||
|
balance: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
exportKbTime: {
|
||||||
|
// Every half hour
|
||||||
|
type: Date
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 新增: 定义 pays 模型
|
// 新增: 定义 pays 模型
|
||||||
const paySchema = new mongoose.Schema({
|
const paySchema = new mongoose.Schema({
|
||||||
_id: mongoose.Schema.Types.ObjectId,
|
|
||||||
userId: mongoose.Schema.Types.ObjectId,
|
userId: mongoose.Schema.Types.ObjectId,
|
||||||
price: Number,
|
price: Number,
|
||||||
orderId: String,
|
orderId: String,
|
||||||
@@ -47,7 +64,6 @@ const paySchema = new mongoose.Schema({
|
|||||||
|
|
||||||
// 新增: 定义 kb 模型
|
// 新增: 定义 kb 模型
|
||||||
const kbSchema = new mongoose.Schema({
|
const kbSchema = new mongoose.Schema({
|
||||||
_id: mongoose.Schema.Types.ObjectId,
|
|
||||||
userId: mongoose.Schema.Types.ObjectId,
|
userId: mongoose.Schema.Types.ObjectId,
|
||||||
avatar: String,
|
avatar: String,
|
||||||
name: String,
|
name: String,
|
||||||
@@ -98,8 +114,8 @@ const SystemSchema = new mongoose.Schema({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const App = mongoose.models['app'] || mongoose.model('app', appSchema);
|
export const App = mongoose.models['model'] || mongoose.model('model', appSchema);
|
||||||
export const Kb = mongoose.models['kb'] || mongoose.model('kb', kbSchema);
|
export const Kb = mongoose.models['kb'] || mongoose.model('kb', kbSchema);
|
||||||
export const User = mongoose.models['user'] || mongoose.model('user', userSchema);
|
export const User = mongoose.models['user'] || mongoose.model('user', UserSchema);
|
||||||
export const Pay = mongoose.models['pay'] || mongoose.model('pay', paySchema);
|
export const Pay = mongoose.models['pay'] || mongoose.model('pay', paySchema);
|
||||||
export const System = mongoose.models['system'] || mongoose.model('system', SystemSchema);
|
export const System = mongoose.models['system'] || mongoose.model('system', SystemSchema);
|
||||||
|
@@ -9,7 +9,7 @@ import {
|
|||||||
HTTPClient
|
HTTPClient
|
||||||
} from 'tushan';
|
} from 'tushan';
|
||||||
import { authProvider } from './auth';
|
import { authProvider } from './auth';
|
||||||
import { userFields, payFields, kbFields, AppFields, SystemFields } from './fields';
|
import { userFields, payFields, kbFields, AppFields } from './fields';
|
||||||
import { Dashboard } from './Dashboard';
|
import { Dashboard } from './Dashboard';
|
||||||
import { IconUser, IconApps, IconBook, IconStamp } from 'tushan/icon';
|
import { IconUser, IconApps, IconBook, IconStamp } from 'tushan/icon';
|
||||||
import { i18nZhTranslation } from 'tushan/client/i18n/resources/zh';
|
import { i18nZhTranslation } from 'tushan/client/i18n/resources/zh';
|
||||||
@@ -64,7 +64,7 @@ function App() {
|
|||||||
})
|
})
|
||||||
]}
|
]}
|
||||||
fields={userFields}
|
fields={userFields}
|
||||||
action={{ detail: true, edit: true }}
|
action={{ create: true, detail: true, edit: true }}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -122,17 +122,6 @@ function App() {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Resource
|
|
||||||
name="system"
|
|
||||||
label="系统"
|
|
||||||
list={
|
|
||||||
<ListTable
|
|
||||||
fields={SystemFields}
|
|
||||||
action={{ detail: true, edit: true, create: true, delete: true }}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Tushan>
|
</Tushan>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -2,9 +2,13 @@ import { createTextField, createNumberField } from 'tushan';
|
|||||||
|
|
||||||
export const userFields = [
|
export const userFields = [
|
||||||
createTextField('id', { label: 'ID' }),
|
createTextField('id', { label: 'ID' }),
|
||||||
createTextField('username', { label: '用户名', edit: { hidden: true } }),
|
createTextField('username', { label: '用户名' }),
|
||||||
createNumberField('balance', { label: '余额', list: { sort: true } }),
|
createNumberField('balance', { label: '余额(元)', list: { sort: true } }),
|
||||||
createTextField('createTime', { label: 'Create Time', list: { sort: true } }),
|
createTextField('createTime', {
|
||||||
|
label: '创建时间',
|
||||||
|
list: { sort: true },
|
||||||
|
edit: { hidden: true }
|
||||||
|
}),
|
||||||
createTextField('password', { label: '密码', list: { hidden: true } })
|
createTextField('password', { label: '密码', list: { hidden: true } })
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -14,7 +18,7 @@ export const payFields = [
|
|||||||
createNumberField('price', { label: '支付金额' }),
|
createNumberField('price', { label: '支付金额' }),
|
||||||
createTextField('orderId', { label: 'orderId' }),
|
createTextField('orderId', { label: 'orderId' }),
|
||||||
createTextField('status', { label: '状态' }),
|
createTextField('status', { label: '状态' }),
|
||||||
createTextField('createTime', { label: 'Create Time', list: { sort: true } })
|
createTextField('createTime', { label: '创建时间', list: { sort: true } })
|
||||||
];
|
];
|
||||||
|
|
||||||
export const kbFields = [
|
export const kbFields = [
|
||||||
@@ -43,10 +47,3 @@ export const AppFields = [
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
export const SystemFields = [
|
|
||||||
createTextField('vectorMaxProcess', { label: '向量最大进程' }),
|
|
||||||
createTextField('qaMaxProcess', { label: 'qa最大进程' }),
|
|
||||||
createTextField('pgIvfflatProbe', { label: 'pg 探针数量' }),
|
|
||||||
createTextField('sensitiveCheck', { label: '敏感词校验(true,false)' })
|
|
||||||
];
|
|
||||||
|
Reference in New Issue
Block a user