feat: 添加登陆日志功能
parent
a693960017
commit
868769880e
Binary file not shown.
|
|
@ -30,12 +30,15 @@
|
||||||
"endOfLine": "auto"
|
"endOfLine": "auto"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@nestjs/axios": "^3.0.0",
|
||||||
"@nestjs/common": "^9.0.0",
|
"@nestjs/common": "^9.0.0",
|
||||||
"@nestjs/core": "^9.0.0",
|
"@nestjs/core": "^9.0.0",
|
||||||
"@nestjs/platform-express": "^9.0.0",
|
"@nestjs/platform-express": "^9.0.0",
|
||||||
|
"axios": "^1.5.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rxjs": "^7.2.0"
|
"rxjs": "^7.2.0",
|
||||||
|
"ua-parser-js": "^1.0.36"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/cache-manager": "^2.1.0",
|
"@nestjs/cache-manager": "^2.1.0",
|
||||||
|
|
|
||||||
2287
pnpm-lock.yaml
2287
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -4,7 +4,7 @@ import { AuthService } from './auth.service';
|
||||||
import { AuthUserDto } from './dto/auth-user.dto';
|
import { AuthUserDto } from './dto/auth-user.dto';
|
||||||
import { Public } from './jwt';
|
import { Public } from './jwt';
|
||||||
import { LoginedUserVo } from './vo/logined-user.vo';
|
import { LoginedUserVo } from './vo/logined-user.vo';
|
||||||
import { AuthLogInterceptor } from '@/monitor/log';
|
import { LoginLogInterceptor } from '@/monitor/log';
|
||||||
|
|
||||||
@ApiTags('auth')
|
@ApiTags('auth')
|
||||||
@Controller('auth')
|
@Controller('auth')
|
||||||
|
|
@ -17,7 +17,7 @@ export class AuthController {
|
||||||
@Post('login')
|
@Post('login')
|
||||||
@Public()
|
@Public()
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@UseInterceptors(AuthLogInterceptor)
|
@UseInterceptors(LoginLogInterceptor)
|
||||||
login(@Body() user: AuthUserDto): Promise<LoginedUserVo> {
|
login(@Body() user: AuthUserDto): Promise<LoginedUserVo> {
|
||||||
return this.authService.signIn(user);
|
return this.authService.signIn(user);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@ import { AuthController } from './auth.controller';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service';
|
||||||
import { JwtGuard, JwtModule } from './jwt';
|
import { JwtGuard, JwtModule } from './jwt';
|
||||||
import { APP_GUARD } from '@nestjs/core';
|
import { APP_GUARD } from '@nestjs/core';
|
||||||
|
import { LogModule } from '@/monitor/log';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [UserModule, JwtModule, LogModule],
|
||||||
controllers: [AuthController],
|
controllers: [AuthController],
|
||||||
imports: [UserModule, JwtModule],
|
|
||||||
providers: [
|
providers: [
|
||||||
AuthService,
|
AuthService,
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,15 @@ export class AuthService {
|
||||||
constructor(private userService: UserService, private jwtService: JwtService) {}
|
constructor(private userService: UserService, private jwtService: JwtService) {}
|
||||||
|
|
||||||
async signIn(authUserDto: AuthUserDto) {
|
async signIn(authUserDto: AuthUserDto) {
|
||||||
const { password, ...user } = await this.userService.findByUsername(authUserDto.username);
|
const user = await this.userService.findByUsername(authUserDto.username);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new UnauthorizedException('用户名不存在');
|
throw new UnauthorizedException('用户名不存在');
|
||||||
}
|
}
|
||||||
if (password !== authUserDto.password) {
|
if (user.password !== authUserDto.password) {
|
||||||
throw new UnauthorizedException('密码错误');
|
throw new UnauthorizedException('密码错误');
|
||||||
}
|
}
|
||||||
const loginedUser = Object.assign(new LoginedUserVo(), user);
|
const { password, ...rest } = user;
|
||||||
|
const loginedUser = Object.assign(new LoginedUserVo(), rest);
|
||||||
const { id, username, nickname } = loginedUser;
|
const { id, username, nickname } = loginedUser;
|
||||||
loginedUser.token = await this.jwtService.signAsync({ id, username, nickname });
|
loginedUser.token = await this.jwtService.signAsync({ id, username, nickname });
|
||||||
return loginedUser;
|
return loginedUser;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,11 @@ import { BaseEntity } from '@/database';
|
||||||
import { Role } from '@/modules/role/entities/role.entity';
|
import { Role } from '@/modules/role/entities/role.entity';
|
||||||
import { Column, Entity, ManyToMany } from 'typeorm';
|
import { Column, Entity, ManyToMany } from 'typeorm';
|
||||||
|
|
||||||
|
enum PermissionType {
|
||||||
|
Menu = 'menu',
|
||||||
|
Api = 'api',
|
||||||
|
}
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Permission extends BaseEntity {
|
export class Permission extends BaseEntity {
|
||||||
/**
|
/**
|
||||||
|
|
@ -10,21 +15,31 @@ export class Permission extends BaseEntity {
|
||||||
*/
|
*/
|
||||||
@Column({ comment: '权限名称' })
|
@Column({ comment: '权限名称' })
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限标识
|
* 权限标识
|
||||||
* @example 'post:list'
|
* @example 'post:list'
|
||||||
*/
|
*/
|
||||||
@Column({ comment: '权限标识' })
|
@Column({ comment: '权限标识' })
|
||||||
slug: string;
|
slug: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限类型
|
||||||
|
* @example 'menu'
|
||||||
|
*/
|
||||||
|
@Column({ nullable: true })
|
||||||
|
type: PermissionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限描述
|
* 权限描述
|
||||||
* @example '文章列表'
|
* @example '文章列表'
|
||||||
*/
|
*/
|
||||||
@Column({ comment: '权限描述', nullable: true })
|
@Column({ comment: '权限描述', nullable: true })
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限角色
|
* 权限角色
|
||||||
* @example '文章列表'
|
* @example {}
|
||||||
*/
|
*/
|
||||||
@ManyToMany(() => Role, (role) => role.permissions)
|
@ManyToMany(() => Role, (role) => role.permissions)
|
||||||
roles: Role[];
|
roles: Role[];
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||||
import { CreatePermissionDto } from './dto/create-permission.dto';
|
import { CreatePermissionDto } from './dto/create-permission.dto';
|
||||||
import { UpdatePermissionDto } from './dto/update-permission.dto';
|
import { UpdatePermissionDto } from './dto/update-permission.dto';
|
||||||
import { PermissionService } from './permission.service';
|
import { PermissionService } from './permission.service';
|
||||||
|
import { PermissionWith } from './permission.decorator';
|
||||||
|
|
||||||
@ApiTags('permission')
|
@ApiTags('permission')
|
||||||
@Controller('permissions')
|
@Controller('permissions')
|
||||||
|
|
@ -11,6 +12,7 @@ export class PermissionController {
|
||||||
constructor(private readonly permissionService: PermissionService) {}
|
constructor(private readonly permissionService: PermissionService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@PermissionWith('permission:add')
|
||||||
@ApiOperation({ description: '创建权限', operationId: 'addPermission' })
|
@ApiOperation({ description: '创建权限', operationId: 'addPermission' })
|
||||||
create(@Body() createPermissionDto: CreatePermissionDto) {
|
create(@Body() createPermissionDto: CreatePermissionDto) {
|
||||||
return this.permissionService.create(createPermissionDto);
|
return this.permissionService.create(createPermissionDto);
|
||||||
|
|
@ -30,7 +32,7 @@ export class PermissionController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@ApiOperation({ description: '更新权限', operationId: 'updatePermission' })
|
@ApiOperation({ description: '更新权限', operationId: 'setPermission' })
|
||||||
update(@Param('id') id: string, @Body() updatePermissionDto: UpdatePermissionDto) {
|
update(@Param('id') id: string, @Body() updatePermissionDto: UpdatePermissionDto) {
|
||||||
return this.permissionService.update(+id, updatePermissionDto);
|
return this.permissionService.update(+id, updatePermissionDto);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { SetMetadata } from '@nestjs/common';
|
import { SetMetadata } from '@nestjs/common';
|
||||||
|
|
||||||
export const PERMISSION_KEY = 'permission';
|
export const PERMISSION_KEY = 'APP:PERMISSION';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限枚举
|
* 权限枚举
|
||||||
|
|
@ -25,10 +25,10 @@ export const enum PermissionEnum {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限装饰器
|
* 指定所需的权限
|
||||||
* @param permissions
|
* @param permissions
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function NeedPermission(...permissions: PermissionEnum[]) {
|
export function PermissionWith(...permissions: string[]) {
|
||||||
return SetMetadata(PERMISSION_KEY, permissions);
|
return SetMetadata(PERMISSION_KEY, permissions);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
import { PaginationDto } from '@/common/response';
|
import { PaginationDto } from '@/common/response';
|
||||||
import { IntersectionType } from '@nestjs/swagger';
|
import { IntersectionType } from '@nestjs/swagger';
|
||||||
|
import { Transform } from 'class-transformer';
|
||||||
import { IsOptional, IsString } from 'class-validator';
|
import { IsOptional, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class FindLogDto extends IntersectionType(PaginationDto) {
|
export class FindLogDto extends IntersectionType(PaginationDto) {
|
||||||
/**
|
/**
|
||||||
* 字段描述(Swagger用途)
|
* 用户名
|
||||||
* @example '示例值'
|
* @example '绝弹'
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
demo?: string;
|
@Transform(({ value }) => value && value.trim())
|
||||||
|
nickname?: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
export class Log {}
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { BaseEntity } from '@/database';
|
||||||
|
import { Column, Entity } from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ orderBy: { id: 'DESC' } })
|
||||||
|
export class LoginLog extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
* @example '绝弹'
|
||||||
|
*/
|
||||||
|
@Column()
|
||||||
|
nickname: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作描述
|
||||||
|
* @example 1
|
||||||
|
*/
|
||||||
|
@Column()
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作状态
|
||||||
|
* @example true
|
||||||
|
*/
|
||||||
|
@Column({ nullable: true })
|
||||||
|
status: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登陆IP
|
||||||
|
* @example '127.0.0.1'
|
||||||
|
*/
|
||||||
|
@Column()
|
||||||
|
ip: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登陆地址
|
||||||
|
* @example '广东省深圳市'
|
||||||
|
*/
|
||||||
|
@Column()
|
||||||
|
addr: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浏览器
|
||||||
|
* @example 'chrome'
|
||||||
|
*/
|
||||||
|
@Column()
|
||||||
|
browser: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作系统
|
||||||
|
* @example 'windows 10'
|
||||||
|
*/
|
||||||
|
@Column()
|
||||||
|
os: string;
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ import { BaseEntity } from '@/database';
|
||||||
import { Column, Entity } from 'typeorm';
|
import { Column, Entity } from 'typeorm';
|
||||||
|
|
||||||
@Entity({ orderBy: { id: 'DESC' } })
|
@Entity({ orderBy: { id: 'DESC' } })
|
||||||
export class AuthLog extends BaseEntity {
|
export class OperationLog extends BaseEntity {
|
||||||
/**
|
/**
|
||||||
* 用户昵称
|
* 用户昵称
|
||||||
* @example '绝弹'
|
* @example '绝弹'
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
export * from './entities/authLog.entity';
|
export * from './entities/loginLog.entity';
|
||||||
export * from './log.controller';
|
export * from './log.controller';
|
||||||
export * from './log.module';
|
export * from './log.module';
|
||||||
export * from './log.service';
|
export * from './log.service';
|
||||||
export * from './interceptors/authLog.interceptor';
|
export * from './interceptors/loginLog.interceptor';
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
|
||||||
import { Observable, tap } from 'rxjs';
|
|
||||||
import { LogService } from '../log.service';
|
|
||||||
|
|
||||||
export class AuthLogInterceptor implements NestInterceptor {
|
|
||||||
constructor(private logger: LogService) {}
|
|
||||||
|
|
||||||
intercept(context: ExecutionContext, next: CallHandler<any>): Observable<any> | Promise<Observable<any>> {
|
|
||||||
return next.handle().pipe(
|
|
||||||
tap({
|
|
||||||
next(data) {
|
|
||||||
console.log('auth ok', data);
|
|
||||||
},
|
|
||||||
error(err) {
|
|
||||||
console.log('auth err', err);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
success() {}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
|
||||||
|
import { Observable, tap } from 'rxjs';
|
||||||
|
import { LogService } from '../log.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class LoginLogInterceptor implements NestInterceptor {
|
||||||
|
constructor(private logService: LogService) {}
|
||||||
|
|
||||||
|
intercept(context: ExecutionContext, next: CallHandler<any>): Observable<any> | Promise<Observable<any>> {
|
||||||
|
const _this = this;
|
||||||
|
return next.handle().pipe(
|
||||||
|
tap({
|
||||||
|
next(data) {
|
||||||
|
const status = true;
|
||||||
|
const description = '登录成功';
|
||||||
|
_this.recordLoginLog(context, { status, description });
|
||||||
|
},
|
||||||
|
error(err) {
|
||||||
|
const status = false;
|
||||||
|
const description = err?.message || '登录失败';
|
||||||
|
_this.recordLoginLog(context, { status, description });
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
recordLoginLog(context: ExecutionContext, data: { status: boolean; description: string }) {
|
||||||
|
const { ip, body, headers } = context.switchToHttp().getRequest();
|
||||||
|
const { status, description } = data;
|
||||||
|
const userAgent = headers['user-agent'] as string;
|
||||||
|
const forwradIp = headers['x-forwarded-for'] as string;
|
||||||
|
const nickname = body.username;
|
||||||
|
this.logService.addLoginLog({
|
||||||
|
nickname,
|
||||||
|
status,
|
||||||
|
description,
|
||||||
|
userAgent,
|
||||||
|
ip: forwradIp || ip,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||||
import { CreateLogDto } from './dto/create-log.dto';
|
import { CreateLogDto } from './dto/create-log.dto';
|
||||||
import { FindLogDto } from './dto/find-log.dto';
|
import { FindLogDto } from './dto/find-log.dto';
|
||||||
import { UpdateLogDto } from './dto/update-log.dto';
|
import { UpdateLogDto } from './dto/update-log.dto';
|
||||||
import { AuthLog } from './entities/authLog.entity';
|
import { LoginLog } from './entities/loginLog.entity';
|
||||||
import { LogService } from './log.service';
|
import { LogService } from './log.service';
|
||||||
|
|
||||||
@ApiTags('log')
|
@ApiTags('log')
|
||||||
|
|
@ -28,16 +28,23 @@ export class LogController extends BaseController {
|
||||||
*/
|
*/
|
||||||
@Get()
|
@Get()
|
||||||
@Respond(RespondType.PAGINATION)
|
@Respond(RespondType.PAGINATION)
|
||||||
@ApiOkResponse({ isArray: true, type: AuthLog })
|
@ApiOkResponse({ isArray: true, type: LoginLog })
|
||||||
getLogs(@Query() query: FindLogDto) {
|
getLogs(@Query() query: FindLogDto) {
|
||||||
return this.logService.findMany(query);
|
return this.logService.findMany(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('login')
|
||||||
|
@Respond(RespondType.PAGINATION)
|
||||||
|
@ApiOkResponse({ isArray: true, type: LoginLog })
|
||||||
|
getLoginLogs(@Query() query: FindLogDto) {
|
||||||
|
return this.logService.findMany(query);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID查询日志管理
|
* 根据ID查询日志管理
|
||||||
*/
|
*/
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
getLog(@Param('id', ParseIntPipe) id: number): Promise<AuthLog> {
|
getLog(@Param('id', ParseIntPipe) id: number): Promise<LoginLog> {
|
||||||
return this.logService.findOne(id);
|
return this.logService.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { AuthLog } from './entities/authLog.entity';
|
import { LoginLog } from './entities/loginLog.entity';
|
||||||
import { LogController } from './log.controller';
|
import { LogController } from './log.controller';
|
||||||
import { LogService } from './log.service';
|
import { LogService } from './log.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([AuthLog])],
|
imports: [TypeOrmModule.forFeature([LoginLog])],
|
||||||
controllers: [LogController],
|
controllers: [LogController],
|
||||||
providers: [LogService],
|
providers: [LogService],
|
||||||
exports: [LogService],
|
exports: [LogService],
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,13 @@ import { Like, Repository } from 'typeorm';
|
||||||
import { CreateLogDto } from './dto/create-log.dto';
|
import { CreateLogDto } from './dto/create-log.dto';
|
||||||
import { FindLogDto } from './dto/find-log.dto';
|
import { FindLogDto } from './dto/find-log.dto';
|
||||||
import { UpdateLogDto } from './dto/update-log.dto';
|
import { UpdateLogDto } from './dto/update-log.dto';
|
||||||
import { AuthLog } from './entities/authLog.entity';
|
import { LoginLog } from './entities/loginLog.entity';
|
||||||
|
import uaParser from 'ua-parser-js';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LogService extends BaseService {
|
export class LogService extends BaseService {
|
||||||
constructor(@InjectRepository(AuthLog) private logRepository: Repository<AuthLog>) {
|
constructor(@InjectRepository(LoginLog) private loginLogRepository: Repository<LoginLog>) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17,39 +19,97 @@ export class LogService extends BaseService {
|
||||||
* 新增日志管理
|
* 新增日志管理
|
||||||
*/
|
*/
|
||||||
async create(createLogDto: CreateLogDto) {
|
async create(createLogDto: CreateLogDto) {
|
||||||
const log = this.logRepository.create();
|
const log = this.loginLogRepository.create();
|
||||||
await this.logRepository.save(log);
|
await this.loginLogRepository.save(log);
|
||||||
return log.id;
|
return log.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加登陆日志
|
||||||
|
*/
|
||||||
|
async addLoginLog(log: { nickname: string; status: boolean, description: string; ip: string; userAgent: string }) {
|
||||||
|
const { nickname, status, description, ip, userAgent } = log;
|
||||||
|
const { browser, os } = this.parseUserAgent(userAgent);
|
||||||
|
const { addr } = await this.parseUserIp(ip);
|
||||||
|
const loginLog = this.loginLogRepository.create({
|
||||||
|
nickname,
|
||||||
|
status,
|
||||||
|
description,
|
||||||
|
ip,
|
||||||
|
addr,
|
||||||
|
browser,
|
||||||
|
os,
|
||||||
|
});
|
||||||
|
await this.loginLogRepository.save(loginLog);
|
||||||
|
return loginLog.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析浏览器信息
|
||||||
|
*/
|
||||||
|
parseUserAgent(userAgent: string) {
|
||||||
|
const ua = uaParser(userAgent);
|
||||||
|
const { browser, os } = ua;
|
||||||
|
return {
|
||||||
|
browser: `${browser.name} ${browser.version}`,
|
||||||
|
os: `${os.name} ${os.version}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析IP地址
|
||||||
|
*/
|
||||||
|
async parseUserIp(ip: string) {
|
||||||
|
const result = {
|
||||||
|
addr: '',
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const url = 'https://whois.pconline.com.cn/ipJson.jsp';
|
||||||
|
const params = { ip, json: true };
|
||||||
|
const { data } = await axios.get(url, { params, responseType: 'arraybuffer' });
|
||||||
|
const dataStr = new TextDecoder('gbk').decode(data);
|
||||||
|
const parased = JSON.parse(dataStr);
|
||||||
|
result.addr = parased.addr;
|
||||||
|
} catch {
|
||||||
|
result.addr = '未知';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 条件/分页查询
|
* 条件/分页查询
|
||||||
*/
|
*/
|
||||||
async findMany(findLogdto: FindLogDto) {
|
async findMany(findLogdto: FindLogDto) {
|
||||||
const { page, size } = findLogdto;
|
const { page, size, nickname } = findLogdto;
|
||||||
const { skip, take } = this.formatPagination(page, size, true);
|
const { skip, take } = this.formatPagination(page, size, true);
|
||||||
return this.logRepository.findAndCount({ skip, take });
|
return this.loginLogRepository.findAndCount({
|
||||||
|
skip,
|
||||||
|
take,
|
||||||
|
where: {
|
||||||
|
nickname: nickname ? Like(`%${nickname}%`) : undefined,
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID查询
|
* 根据ID查询
|
||||||
*/
|
*/
|
||||||
findOne(idOrOptions: number | Partial<AuthLog>) {
|
findOne(idOrOptions: number | Partial<LoginLog>) {
|
||||||
const where = typeof idOrOptions === 'number' ? { id: idOrOptions } : (idOrOptions as any);
|
const where = typeof idOrOptions === 'number' ? { id: idOrOptions } : (idOrOptions as any);
|
||||||
return this.logRepository.findOne({ where });
|
return this.loginLogRepository.findOne({ where });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID更新
|
* 根据ID更新
|
||||||
*/
|
*/
|
||||||
update(id: number, updateLogDto: UpdateLogDto) {
|
update(id: number, updateLogDto: UpdateLogDto) {
|
||||||
// return this.logRepository.update();
|
// return this.loginLogRepository.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID删除(软删除)
|
* 根据ID删除(软删除)
|
||||||
*/
|
*/
|
||||||
remove(id: number) {
|
remove(id: number) {
|
||||||
return this.logRepository.softDelete(id);
|
return this.loginLogRepository.softDelete(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue