This commit is contained in:
parent
f149f20052
commit
6b67107b8c
|
@ -4,14 +4,9 @@ import {
|
||||||
BadRequestException,
|
BadRequestException,
|
||||||
Logger,
|
Logger,
|
||||||
InternalServerErrorException,
|
InternalServerErrorException,
|
||||||
|
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { StaffService } from '../models/staff/staff.service';
|
import { StaffService } from '../models/staff/staff.service';
|
||||||
import {
|
import { db, AuthSchema, JwtPayload } from '@nice/common';
|
||||||
db,
|
|
||||||
AuthSchema,
|
|
||||||
JwtPayload,
|
|
||||||
} from '@nice/common';
|
|
||||||
import * as argon2 from 'argon2';
|
import * as argon2 from 'argon2';
|
||||||
import { JwtService } from '@nestjs/jwt';
|
import { JwtService } from '@nestjs/jwt';
|
||||||
import { redis } from '@server/utils/redis/redis.service';
|
import { redis } from '@server/utils/redis/redis.service';
|
||||||
|
@ -24,14 +19,12 @@ import { TusService } from '@server/upload/tus.service';
|
||||||
import { extractFileIdFromNginxUrl } from '@server/upload/utils';
|
import { extractFileIdFromNginxUrl } from '@server/upload/utils';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
private logger = new Logger(AuthService.name)
|
private logger = new Logger(AuthService.name);
|
||||||
constructor(
|
constructor(
|
||||||
private readonly staffService: StaffService,
|
private readonly staffService: StaffService,
|
||||||
private readonly jwtService: JwtService,
|
private readonly jwtService: JwtService,
|
||||||
private readonly sessionService: SessionService
|
private readonly sessionService: SessionService,
|
||||||
) {
|
) {}
|
||||||
|
|
||||||
}
|
|
||||||
async validateFileRequest(params: FileRequest): Promise<FileAuthResult> {
|
async validateFileRequest(params: FileRequest): Promise<FileAuthResult> {
|
||||||
try {
|
try {
|
||||||
// 基础参数验证
|
// 基础参数验证
|
||||||
|
@ -39,27 +32,32 @@ export class AuthService {
|
||||||
return { isValid: false, error: FileValidationErrorType.INVALID_URI };
|
return { isValid: false, error: FileValidationErrorType.INVALID_URI };
|
||||||
}
|
}
|
||||||
const fileId = extractFileIdFromNginxUrl(params.originalUri);
|
const fileId = extractFileIdFromNginxUrl(params.originalUri);
|
||||||
console.log(params.originalUri, fileId)
|
console.log(params.originalUri, fileId);
|
||||||
const resource = await db.resource.findFirst({ where: { fileId } });
|
const resource = await db.resource.findFirst({ where: { fileId } });
|
||||||
|
|
||||||
// 资源验证
|
// 资源验证
|
||||||
if (!resource) {
|
if (!resource) {
|
||||||
return { isValid: false, error: FileValidationErrorType.RESOURCE_NOT_FOUND };
|
return {
|
||||||
|
isValid: false,
|
||||||
|
error: FileValidationErrorType.RESOURCE_NOT_FOUND,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// 处理公开资源
|
// 处理公开资源
|
||||||
if (resource.isPublic) {
|
if (resource.isPublic) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
resourceType: resource.type || 'unknown'
|
resourceType: resource.type || 'unknown',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// 处理私有资源
|
// 处理私有资源
|
||||||
const token = extractTokenFromAuthorization(params.authorization);
|
const token = extractTokenFromAuthorization(params.authorization);
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return { isValid: false, error: FileValidationErrorType.AUTHORIZATION_REQUIRED };
|
return {
|
||||||
|
isValid: false,
|
||||||
|
error: FileValidationErrorType.AUTHORIZATION_REQUIRED,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
const payload: JwtPayload = await this.jwtService.verify(token)
|
const payload: JwtPayload = await this.jwtService.verify(token);
|
||||||
if (!payload.sub) {
|
if (!payload.sub) {
|
||||||
return { isValid: false, error: FileValidationErrorType.INVALID_TOKEN };
|
return { isValid: false, error: FileValidationErrorType.INVALID_TOKEN };
|
||||||
}
|
}
|
||||||
|
@ -67,9 +65,8 @@ export class AuthService {
|
||||||
return {
|
return {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
userId: payload.sub,
|
userId: payload.sub,
|
||||||
resourceType: resource.type || 'unknown'
|
resourceType: resource.type || 'unknown',
|
||||||
};
|
};
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('File validation error:', error);
|
this.logger.error('File validation error:', error);
|
||||||
return { isValid: false, error: FileValidationErrorType.UNKNOWN_ERROR };
|
return { isValid: false, error: FileValidationErrorType.UNKNOWN_ERROR };
|
||||||
|
@ -93,7 +90,9 @@ export class AuthService {
|
||||||
return { accessToken, refreshToken };
|
return { accessToken, refreshToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
async signIn(data: z.infer<typeof AuthSchema.signInRequset>): Promise<SessionInfo> {
|
async signIn(
|
||||||
|
data: z.infer<typeof AuthSchema.signInRequset>,
|
||||||
|
): Promise<SessionInfo> {
|
||||||
const { username, password, phoneNumber } = data;
|
const { username, password, phoneNumber } = data;
|
||||||
|
|
||||||
let staff = await db.staff.findFirst({
|
let staff = await db.staff.findFirst({
|
||||||
|
@ -113,7 +112,8 @@ export class AuthService {
|
||||||
if (!staff.enabled) {
|
if (!staff.enabled) {
|
||||||
throw new UnauthorizedException('帐号已禁用');
|
throw new UnauthorizedException('帐号已禁用');
|
||||||
}
|
}
|
||||||
const isPasswordMatch = phoneNumber || await argon2.verify(staff.password, password);
|
const isPasswordMatch =
|
||||||
|
phoneNumber || (await argon2.verify(staff.password, password));
|
||||||
if (!isPasswordMatch) {
|
if (!isPasswordMatch) {
|
||||||
throw new UnauthorizedException('帐号或密码错误');
|
throw new UnauthorizedException('帐号或密码错误');
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ export class AuthService {
|
||||||
const existingUser = await db.staff.findFirst({
|
const existingUser = await db.staff.findFirst({
|
||||||
where: {
|
where: {
|
||||||
OR: [{ username }, { officerId }, { phoneNumber }],
|
OR: [{ username }, { officerId }, { phoneNumber }],
|
||||||
deletedAt: null
|
deletedAt: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ export class AuthService {
|
||||||
data: {
|
data: {
|
||||||
...data,
|
...data,
|
||||||
domainId: data.deptId,
|
domainId: data.deptId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async refreshToken(data: z.infer<typeof AuthSchema.refreshTokenRequest>) {
|
async refreshToken(data: z.infer<typeof AuthSchema.refreshTokenRequest>) {
|
||||||
|
@ -168,12 +168,17 @@ export class AuthService {
|
||||||
throw new UnauthorizedException('用户会话已过期');
|
throw new UnauthorizedException('用户会话已过期');
|
||||||
}
|
}
|
||||||
|
|
||||||
const session = await this.sessionService.getSession(payload.sub, sessionId);
|
const session = await this.sessionService.getSession(
|
||||||
|
payload.sub,
|
||||||
|
sessionId,
|
||||||
|
);
|
||||||
if (!session || session.refresh_token !== refreshToken) {
|
if (!session || session.refresh_token !== refreshToken) {
|
||||||
throw new UnauthorizedException('用户会话已过期');
|
throw new UnauthorizedException('用户会话已过期');
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await db.staff.findUnique({ where: { id: payload.sub, deletedAt: null } });
|
const user = await db.staff.findUnique({
|
||||||
|
where: { id: payload.sub, deletedAt: null },
|
||||||
|
});
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new UnauthorizedException('用户不存在');
|
throw new UnauthorizedException('用户不存在');
|
||||||
}
|
}
|
||||||
|
@ -186,14 +191,17 @@ export class AuthService {
|
||||||
const updatedSession = {
|
const updatedSession = {
|
||||||
...session,
|
...session,
|
||||||
access_token: accessToken,
|
access_token: accessToken,
|
||||||
access_token_expires_at: Date.now() + tokenConfig.accessToken.expirationMs,
|
access_token_expires_at:
|
||||||
|
Date.now() + tokenConfig.accessToken.expirationMs,
|
||||||
};
|
};
|
||||||
await this.sessionService.saveSession(
|
await this.sessionService.saveSession(
|
||||||
payload.sub,
|
payload.sub,
|
||||||
updatedSession,
|
updatedSession,
|
||||||
tokenConfig.accessToken.expirationTTL,
|
tokenConfig.accessToken.expirationTTL,
|
||||||
);
|
);
|
||||||
await redis.del(UserProfileService.instance.getProfileCacheKey(payload.sub));
|
await redis.del(
|
||||||
|
UserProfileService.instance.getProfileCacheKey(payload.sub),
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
access_token: accessToken,
|
access_token: accessToken,
|
||||||
access_token_expires_at: updatedSession.access_token_expires_at,
|
access_token_expires_at: updatedSession.access_token_expires_at,
|
||||||
|
@ -212,7 +220,7 @@ export class AuthService {
|
||||||
where: { id: user?.id },
|
where: { id: user?.id },
|
||||||
data: {
|
data: {
|
||||||
password: newPassword,
|
password: newPassword,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return { message: '密码已修改' };
|
return { message: '密码已修改' };
|
||||||
|
@ -232,5 +240,4 @@ export class AuthService {
|
||||||
|
|
||||||
return { message: '注销成功' };
|
return { message: '注销成功' };
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue