- Deleted `import-data.ts` and `import-life.ts` scripts for importing short-link and life JSON data into the database. - Removed `ncode-list.json` containing short-link data. - Added new script `mv-resources.ts` for migrating resources from username-based paths to userId-based paths in the database and object storage. - Introduced `UserId` module for fetching user IDs and usernames from the database with caching. - Updated `UserApp` class to use user IDs instead of usernames for resource paths. - Modified routes to include a new endpoint for retrieving user IDs based on usernames.
119 lines
3.0 KiB
TypeScript
119 lines
3.0 KiB
TypeScript
import { app, db, schema } from '@/app.ts';
|
|
import { User } from '@/models/user.ts';
|
|
import { CustomError } from '@kevisual/router';
|
|
import { checkUsername } from './admin/user.ts';
|
|
import { nanoid } from 'nanoid';
|
|
import { sql } from 'drizzle-orm';
|
|
import z from 'zod';
|
|
import { UserId } from './modules/user-id.ts';
|
|
|
|
app
|
|
.route({
|
|
path: 'user',
|
|
key: 'list',
|
|
middleware: ['auth'],
|
|
})
|
|
.define(async (ctx) => {
|
|
const users = await db
|
|
.select({
|
|
id: schema.cfUser.id,
|
|
username: schema.cfUser.username,
|
|
description: schema.cfUser.description,
|
|
needChangePassword: schema.cfUser.needChangePassword,
|
|
})
|
|
.from(schema.cfUser)
|
|
.orderBy(sql`${schema.cfUser.updatedAt} DESC`);
|
|
ctx.body = users;
|
|
})
|
|
.addTo(app);
|
|
|
|
app
|
|
.route({
|
|
path: 'user',
|
|
key: 'update',
|
|
middleware: ['auth'],
|
|
})
|
|
.define(async (ctx) => {
|
|
const tokenUser = ctx.state.tokenUser;
|
|
const { id, username, password, description } = ctx.query.data || {};
|
|
if (!id) {
|
|
throw new CustomError(400, { message: 'id is required' });
|
|
}
|
|
const user = await User.findByPk(id);
|
|
if (user.id !== tokenUser.id) {
|
|
throw new CustomError(403, { message: 'Permission denied' });
|
|
}
|
|
|
|
if (!user) {
|
|
throw new CustomError(500, { message: 'user not found' });
|
|
}
|
|
if (username) {
|
|
user.username = username;
|
|
}
|
|
if (password) {
|
|
user.createPassword(password);
|
|
}
|
|
if (description) {
|
|
user.description = description;
|
|
}
|
|
await user.save();
|
|
ctx.body = {
|
|
id: user.id,
|
|
username: user.username,
|
|
description: user.description,
|
|
needChangePassword: user.needChangePassword,
|
|
};
|
|
})
|
|
.addTo(app);
|
|
|
|
app
|
|
.route({
|
|
path: 'user',
|
|
key: 'add',
|
|
middleware: ['auth-admin'],
|
|
})
|
|
.define(async (ctx) => {
|
|
const { username, password, description } = ctx.query.data || {};
|
|
if (!username) {
|
|
throw new CustomError(400, { message: 'username is required' });
|
|
}
|
|
checkUsername(username);
|
|
const findUserByUsername = await User.findOne({ username });
|
|
if (findUserByUsername) {
|
|
throw new CustomError(400, { message: 'username already exists' });
|
|
}
|
|
const pwd = password || nanoid(6);
|
|
const user = await User.createUser(username, pwd, description);
|
|
ctx.body = {
|
|
id: user.id,
|
|
username: user.username,
|
|
description: user.description,
|
|
needChangePassword: user.needChangePassword,
|
|
password: pwd,
|
|
};
|
|
})
|
|
.addTo(app);
|
|
|
|
app.route({
|
|
path: 'user',
|
|
key: 'uid',
|
|
description: '根据用户名获取用户ID',
|
|
middleware: ['auth'],
|
|
metadata: {
|
|
args: {
|
|
username: z.string().describe('username is required'),
|
|
}
|
|
}
|
|
}).define(async (ctx) => {
|
|
const { username } = ctx.query || {};
|
|
if (!username) {
|
|
ctx.throw(400, { message: 'username is required' });
|
|
}
|
|
const userId = await UserId.getUserIdByName(username);
|
|
if (!userId) {
|
|
ctx.throw(404, { message: 'user not found' });
|
|
}
|
|
ctx.body = {
|
|
id: userId,
|
|
};
|
|
}).addTo(app); |