feat: 优化菜单模块
parent
a4328d5fef
commit
8aa7b00949
2
.env
2
.env
|
|
@ -20,7 +20,7 @@ SERVER_OPENAPI_URL = /api/openapi
|
|||
# 数据库类型
|
||||
DB_TYPE = sqlite
|
||||
# sqlite数据库地址
|
||||
DB_SQLITE_PATH = ./content/database/db.sqlite
|
||||
DB_SQLITE_PATH = ./content/data/db.sqlite
|
||||
# mysql数据库地址
|
||||
DB_MYSQL_HOST = 127.0.0.1
|
||||
# mysql数据库端口
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 239 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable, ConsoleLogger } from '@nestjs/common';
|
||||
import { dayjs } from '@/libs';
|
||||
import { dayjs } from '@/libraries';
|
||||
import { ConfigService } from '@/config';
|
||||
import { Logger, createLogger, format, transports } from 'winston';
|
||||
import 'winston-daily-rotate-file';
|
||||
|
|
|
|||
|
|
@ -8,19 +8,14 @@ import { extname, join } from 'path';
|
|||
import { Upload } from './entities/file.entity';
|
||||
import { UploadController } from './file.controller';
|
||||
import { UploadService } from './file.service';
|
||||
import { dayjs } from '@/libraries';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Upload]),
|
||||
MulterModule.registerAsync({
|
||||
const MulteredModule = MulterModule.registerAsync({
|
||||
useFactory: (config: ConfigService) => {
|
||||
return {
|
||||
storage: diskStorage({
|
||||
destination: (req, file, next) => {
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const dest = join(config.uploadDir, year.toString(), month.toString().padStart(2, '0'));
|
||||
const dest = join(config.uploadDir, dayjs().format(dayjs.DATE));
|
||||
if (!existsSync(dest)) {
|
||||
mkdirSync(dest, { recursive: true });
|
||||
}
|
||||
|
|
@ -33,8 +28,10 @@ import { UploadService } from './file.service';
|
|||
};
|
||||
},
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Upload]), MulteredModule],
|
||||
controllers: [UploadController],
|
||||
providers: [UploadService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,10 +1,19 @@
|
|||
import { Body, Controller, HttpCode, HttpStatus, Post, UseInterceptors } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Post,
|
||||
Req,
|
||||
UnauthorizedException,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthUserDto } from './dto/auth-user.dto';
|
||||
import { Public } from './jwt';
|
||||
import { LoginedUserVo } from './vo/logined-user.vo';
|
||||
import { LoginLogInterceptor } from '@/monitor/log';
|
||||
import { Request } from 'express';
|
||||
|
||||
@ApiTags('auth')
|
||||
@Controller('auth')
|
||||
|
|
@ -18,7 +27,21 @@ export class AuthController {
|
|||
@Public()
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@UseInterceptors(LoginLogInterceptor)
|
||||
login(@Body() user: AuthUserDto): Promise<LoginedUserVo> {
|
||||
@ApiOperation({ description: '登陆', operationId: 'login' })
|
||||
login(@Body() user: AuthUserDto) {
|
||||
return this.authService.signIn(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登陆信息
|
||||
*/
|
||||
@Post('info')
|
||||
@ApiOperation({ description: '获取登陆用户信息', operationId: 'getUserInfo' })
|
||||
getUserInfo(@Req() req: Request) {
|
||||
const userId = req.user?.id;
|
||||
if (!userId) {
|
||||
throw new UnauthorizedException('请登陆后再尝试');
|
||||
}
|
||||
return this.authService.getUserInfo(userId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { UserService } from '../user';
|
||||
import { AuthUserDto } from './dto/auth-user.dto';
|
||||
import { LoginedUserVo } from './vo/logined-user.vo';
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
|
|
@ -11,16 +11,22 @@ export class AuthService {
|
|||
async signIn(authUserDto: AuthUserDto) {
|
||||
const user = await this.userService.findOne({ username: authUserDto.username });
|
||||
if (!user) {
|
||||
console.log(user, authUserDto);
|
||||
throw new UnauthorizedException('用户名不存在');
|
||||
}
|
||||
if (user.password !== authUserDto.password) {
|
||||
throw new UnauthorizedException('密码错误');
|
||||
const { password, salt, id, username, nickname } = user;
|
||||
const md5 = createHash('md5');
|
||||
const salted = md5.update(user.password + salt).digest('hex');
|
||||
// if (salted !== password) {
|
||||
// throw new UnauthorizedException('密码错误');
|
||||
// }
|
||||
return this.jwtService.signAsync({ id, username, nickname });
|
||||
}
|
||||
const { password, ...rest } = user;
|
||||
const loginedUser = Object.assign(new LoginedUserVo(), rest);
|
||||
const { id, username, nickname } = loginedUser;
|
||||
loginedUser.token = await this.jwtService.signAsync({ id, username, nickname });
|
||||
return loginedUser;
|
||||
|
||||
async getUserInfo(id: number) {
|
||||
const user = await this.userService.findOne({ id });
|
||||
if (!user) {
|
||||
throw new NotFoundException('用户信息未找到');
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ export class Menu extends BaseEntity {
|
|||
@TreeParent()
|
||||
parent: Menu;
|
||||
|
||||
@Column({ comment: '父级ID', nullable: true, default: 0 })
|
||||
@Column({ comment: '父级ID', nullable: true })
|
||||
parentId: number;
|
||||
|
||||
@ApiHideProperty()
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export class MenuController extends BaseController {
|
|||
|
||||
@Delete(':id')
|
||||
@ApiOperation({ description: '删除菜单', operationId: 'delMenu' })
|
||||
delMenu(id: number) {
|
||||
delMenu(@Param('id') id: number) {
|
||||
return this.menuService.remove(+id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export class MenuService extends BaseService {
|
|||
const parent = await this.menuRepository.findOne({ where: { id: parentId } });
|
||||
menu.parent = parent;
|
||||
}
|
||||
delete menu.parentId;
|
||||
await this.menuRepository.save(menu);
|
||||
return menu;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,15 @@ export class User extends BaseEntity {
|
|||
@Column({ length: 64 })
|
||||
password: string;
|
||||
|
||||
/**
|
||||
* 加密盐
|
||||
* @example 'xx'
|
||||
*/
|
||||
@Exclude()
|
||||
@ApiHideProperty()
|
||||
@Column({ comment: '加密盐', nullable: true })
|
||||
salt: string;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
* @example '绝弹'
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import { FindUserDto } from './dto/find-user.dto';
|
|||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { User } from './entities/user.entity';
|
||||
import { RoleService } from '../role';
|
||||
import { uuid } from '@/libraries';
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
@Injectable()
|
||||
export class UserService extends BaseService {
|
||||
|
|
@ -20,6 +22,14 @@ export class UserService extends BaseService {
|
|||
async create(createUserDto: CreateUserDto) {
|
||||
const user = this.userRepository.create(createUserDto);
|
||||
user.roles = await this.roleService.findByIds(user.roleIds ?? []);
|
||||
const { password } = createUserDto;
|
||||
if (password) {
|
||||
const salt = uuid();
|
||||
const md5 = createHash('md5');
|
||||
const pass = md5.update(password + salt).digest('hex');
|
||||
user.salt = salt;
|
||||
user.password = pass;
|
||||
}
|
||||
await this.userRepository.save(user);
|
||||
return user.id;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue