This commit is contained in:
ditiqi 2025-01-27 22:43:07 +08:00
parent f149f20052
commit 6b67107b8c
1 changed files with 37 additions and 30 deletions

View File

@ -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: '注销成功' };
} }
}
}