fix and update

This commit is contained in:
lendry
2026-07-01 23:27:48 +03:00
parent 2b88e028c6
commit bcdfbc3861
36 changed files with 1504 additions and 320 deletions

View File

@@ -800,13 +800,13 @@ export class AuthGrpcController {
}
@GrpcMethod('MediaService', 'CreateDocumentPhotoUploadUrl')
createDocumentPhotoUploadUrl(command: { userId: string; documentId: string; contentType: string }) {
return this.media.createDocumentPhotoUploadUrl(command.userId, command.documentId, command.contentType);
createDocumentPhotoUploadUrl(command: { userId: string; documentId: string; contentType: string; fileName?: string }) {
return this.media.createDocumentPhotoUploadUrl(command.userId, command.documentId, command.contentType, command.fileName);
}
@GrpcMethod('MediaService', 'GetDocumentPhotoAccessUrl')
getDocumentPhotoAccessUrl(command: { requesterId: string; targetUserId: string; storageKey: string }) {
return this.media.getDocumentPhotoAccessUrl(command.requesterId, command.targetUserId, command.storageKey);
getDocumentPhotoAccessUrl(command: { requesterId: string; targetUserId: string; storageKey: string; fileName?: string }) {
return this.media.getDocumentPhotoAccessUrl(command.requesterId, command.targetUserId, command.storageKey, command.fileName);
}
@GrpcMethod('MediaService', 'ResolveStreamToken')

View File

@@ -115,9 +115,10 @@ export class MediaService {
};
}
async createDocumentPhotoUploadUrl(userId: string, documentId: string, contentType: string) {
async createDocumentPhotoUploadUrl(userId: string, documentId: string, contentType: string, fileName?: string) {
let normalizedContentType: string;
try {
this.minio.assertImageContentType(contentType);
normalizedContentType = this.minio.assertDocumentAttachmentContentType(contentType, fileName);
} catch (error) {
throw new BadRequestException(error instanceof Error ? error.message : 'Некорректный тип файла');
}
@@ -128,9 +129,9 @@ export class MediaService {
throw new NotFoundException('Документ не найден');
}
const extension = this.minio.extensionForContentType(contentType);
const extension = this.minio.extensionForDocumentContentType(normalizedContentType, fileName);
const storageKey = `documents/${userId}/${documentId}/${crypto.randomUUID()}.${extension}`;
return this.createUploadTarget(userId, storageKey, contentType);
return this.createUploadTarget(userId, storageKey, normalizedContentType);
}
async resolveStreamToken(token: string, requesterId?: string) {
@@ -177,18 +178,19 @@ export class MediaService {
);
}
async getDocumentPhotoAccessUrl(requesterId: string, targetUserId: string, storageKey: string) {
async getDocumentPhotoAccessUrl(requesterId: string, targetUserId: string, storageKey: string, fileName?: string) {
await this.access.assertCanViewUserDocuments(requesterId, targetUserId);
if (!storageKey.startsWith(`documents/${targetUserId}/`)) {
throw new BadRequestException('Некорректный ключ фото документа');
throw new BadRequestException('Некорректный ключ файла документа');
}
const token = await this.jwt.signAsync(
{
purpose: 'media-stream',
objectKey: storageKey,
ownerId: targetUserId
ownerId: targetUserId,
fileName: fileName?.trim() || undefined
} satisfies MediaStreamPayload,
{
secret: this.config.getOrThrow<string>('JWT_ACCESS_SECRET'),

View File

@@ -169,6 +169,7 @@ export class PinService {
data: {
pinVerified: true,
status: SessionStatus.ACTIVE,
lastActivityAt: new Date(),
updatedAt: new Date()
}
});

View File

@@ -47,7 +47,8 @@ export class SessionService {
if (pinEnabled && pinVerified && status === SessionStatus.ACTIVE) {
const timeoutMinutes = await this.settings.getNumber('PIN_LOCK_TIMEOUT_MINUTES', 15);
const threshold = new Date(Date.now() - timeoutMinutes * 60_000);
if (session.updatedAt < threshold) {
const lastActivityAt = session.lastActivityAt ?? session.updatedAt;
if (lastActivityAt < threshold) {
await this.prisma.session.update({
where: { id: sessionId },
data: { pinVerified: false, status: SessionStatus.LOCKED }
@@ -76,7 +77,7 @@ export class SessionService {
await this.prisma.session.update({
where: { id: sessionId },
data: { updatedAt: new Date() }
data: { lastActivityAt: new Date(), updatedAt: new Date() }
});
return state;
@@ -160,7 +161,7 @@ export class SessionService {
return this.prisma.session.updateMany({
where: {
pinVerified: true,
updatedAt: { lt: threshold },
lastActivityAt: { lt: threshold },
status: SessionStatus.ACTIVE,
user: { pinCode: { isEnabled: true } }
},