imkFinal/backend/src/admin/admin.service.ts
2025-02-25 20:41:23 +01:00

346 lines
9.9 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { S3Service } from '../s3/s3.service';
import { UpdateDocumentDto } from '../dto/update-document.dto';
import { CreateUserDto } from '../dto/create-user.dto';
import * as bcrypt from 'bcrypt';
import { EmailService } from '../email/email.service';
@Injectable()
export class AdminService {
private readonly logger = new Logger(AdminService.name);
constructor(
private readonly prisma: PrismaService,
private readonly s3Service: S3Service,
private readonly emailService: EmailService,
) {}
async getAllDocuments() {
return this.prisma.document.findMany({
include: {
uploadedBy: {
select: {
id: true,
name: true,
email: true,
},
},
sharedWith: {
select: {
id: true,
name: true,
email: true,
},
},
},
orderBy: {
createdAt: 'desc',
},
});
}
async getAllUsers() {
return this.prisma.user.findMany();
}
async createUser(createUserDto: CreateUserDto) {
const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
return this.prisma.user.create({
data: {
...createUserDto,
password: hashedPassword,
},
});
}
async updateDocument(
id: number,
updateDocumentDto: UpdateDocumentDto,
file?: Express.Multer.File,
) {
let s3Key = undefined;
if (file) {
s3Key = await this.s3Service.uploadFile(file, 'documents');
}
return this.prisma.document.update({
where: { id },
data: {
...updateDocumentDto,
...(s3Key && { s3Key }),
},
});
}
async shareDocument(documentId: number, userId: number) {
this.logger.log('=== Starting document share process ===');
console.log('=== Starting document share process ===');
this.logger.debug('Share request:', { documentId, userId });
console.log('Share request:', { documentId, userId });
try {
// Get the document with its current data
const document = await this.prisma.document.findUnique({
where: { id: documentId },
include: {
uploadedBy: {
select: {
id: true,
name: true,
email: true,
},
},
},
});
if (!document) {
this.logger.error('Document not found:', { documentId });
console.error('Document not found:', { documentId });
throw new Error('Document not found');
}
// Get the user we're sharing with
const shareUser = await this.prisma.user.findUnique({
where: { id: userId },
select: {
id: true,
name: true,
email: true,
},
});
if (!shareUser) {
this.logger.error('User not found:', { userId });
console.error('User not found:', { userId });
throw new Error('User not found');
}
// Update the document sharing
const updatedDocument = await this.prisma.document.update({
where: { id: documentId },
data: {
sharedWith: {
connect: { id: userId },
},
},
include: {
uploadedBy: {
select: {
id: true,
name: true,
email: true,
},
},
sharedWith: {
select: {
id: true,
name: true,
email: true,
},
},
},
});
// Send email notification to the user we're sharing with
this.logger.log('Sending email notification to shared user:', {
userId: shareUser.id,
email: shareUser.email,
name: shareUser.name,
documentTitle: document.title
});
console.log('Sending email notification to shared user:', {
userId: shareUser.id,
email: shareUser.email,
name: shareUser.name,
documentTitle: document.title
});
try {
console.log('Attempting to send email notification...');
await this.emailService.sendDocumentNotification(
shareUser.email,
shareUser.name,
document.title,
'shared'
);
console.log('Email notification sent successfully');
this.logger.log('Email notification sent successfully');
} catch (emailError) {
// Log the full error details
console.error('Failed to send email notification:', emailError);
this.logger.error('Failed to send email notification:', {
error: emailError.message,
code: emailError.code,
command: emailError.command,
response: emailError.response,
responseCode: emailError.responseCode,
stack: emailError.stack,
});
// Don't throw the error, just log it and continue
}
this.logger.log('=== Document share process completed ===');
console.log('=== Document share process completed ===');
return updatedDocument;
} catch (error) {
this.logger.error('Error in shareDocument:', {
error: error.message,
code: error.code,
stack: error.stack,
});
console.error('Error in shareDocument:', error);
throw error;
}
}
async updateDocumentStatus(documentId: number, status: string) {
return this.prisma.document.update({
where: { id: documentId },
data: { status },
});
}
async uploadDocument(
file: Express.Multer.File,
title: string,
sharedWithId: number,
uploadedById: number
) {
this.logger.log('=== Starting document upload process ===');
this.logger.debug('Upload parameters:', {
title,
sharedWithId,
uploadedById,
fileName: file.originalname,
fileSize: file.size,
});
try {
this.logger.debug('Uploading file to S3...');
const s3Key = await this.s3Service.uploadFile(file, 'documents');
this.logger.debug(`File uploaded to S3 successfully with key: ${s3Key}`);
this.logger.debug('Creating document record in database...');
const document = await this.prisma.document.create({
data: {
title,
s3Key,
status: 'pending',
sharedWith: {
connect: { id: sharedWithId }
},
uploadedBy: {
connect: { id: uploadedById }
}
},
include: {
uploadedBy: {
select: {
id: true,
name: true,
email: true,
},
},
sharedWith: {
select: {
id: true,
name: true,
email: true,
},
},
},
});
this.logger.debug('Document record created:', {
id: document.id,
title: document.title,
uploadedBy: document.uploadedBy,
sharedWith: document.sharedWith,
});
// Send email notifications
this.logger.log('=== Starting email notification process ===');
// Notify the user who the document is shared with
const sharedUser = document.sharedWith[0];
if (sharedUser) {
this.logger.debug(`Preparing to send notification to shared user:`, {
id: sharedUser.id,
email: sharedUser.email,
name: sharedUser.name,
});
try {
this.logger.debug('Calling EmailService.sendDocumentNotification for shared user...');
await this.emailService.sendDocumentNotification(
sharedUser.email,
sharedUser.name,
document.title,
'shared'
);
this.logger.debug('Shared user notification sent successfully');
} catch (error) {
this.logger.error('Failed to send notification to shared user:', {
error: error.message,
code: error.code,
command: error.command,
stack: error.stack,
});
// Log the email service instance to verify it's properly injected
this.logger.debug('EmailService instance:', {
exists: !!this.emailService,
type: typeof this.emailService,
methods: Object.keys(Object.getPrototypeOf(this.emailService)),
});
}
} else {
this.logger.warn('No shared user found in the document record');
}
// Notify the uploader
const uploader = document.uploadedBy;
if (uploader) {
this.logger.debug(`Preparing to send notification to uploader:`, {
id: uploader.id,
email: uploader.email,
name: uploader.name,
});
try {
this.logger.debug('Calling EmailService.sendDocumentNotification for uploader...');
await this.emailService.sendDocumentNotification(
uploader.email,
uploader.name,
document.title,
'uploaded'
);
this.logger.debug('Uploader notification sent successfully');
} catch (error) {
this.logger.error('Failed to send notification to uploader:', {
error: error.message,
code: error.code,
command: error.command,
stack: error.stack,
});
// Log the email service instance to verify it's properly injected
this.logger.debug('EmailService instance:', {
exists: !!this.emailService,
type: typeof this.emailService,
methods: Object.keys(Object.getPrototypeOf(this.emailService)),
});
}
} else {
this.logger.warn('No uploader found in the document record');
}
this.logger.log('=== Document upload process completed ===');
return document;
} catch (error) {
this.logger.error('Error in uploadDocument:', {
error: error.message,
code: error.code,
stack: error.stack,
});
throw error;
}
}
}