clients page
This commit is contained in:
1 parent
3d2b0a5d6d
commit
1a7f2afd79
20 files changed
+458
-402
No files matched your search
@@ -71,6 +71,10 @@
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
|
||||
"prisma": {
|
||||
"seed": "ts-node prisma/seed.ts"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"name" TEXT,
|
||||
"password" TEXT NOT NULL,
|
||||
"isAdmin" BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Document" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"content" TEXT,
|
||||
"published" BOOLEAN NOT NULL DEFAULT false,
|
||||
"authorId" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "Document_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Document" ADD CONSTRAINT "Document_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Document" ADD COLUMN "s3Key" TEXT;
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- Made the column `s3Key` on table `Document` required. This step will fail if there are existing NULL values in that column.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Document" ALTER COLUMN "s3Key" SET NOT NULL;
|
||||
+29
-8
@@ -1,13 +1,28 @@
|
||||
/*
|
||||
Warnings:
|
||||
-- CreateTable
|
||||
CREATE TABLE "Document" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"content" TEXT,
|
||||
"published" BOOLEAN NOT NULL DEFAULT false,
|
||||
"authorId" INTEGER NOT NULL,
|
||||
"s3Key" TEXT NOT NULL,
|
||||
"status" TEXT NOT NULL DEFAULT 'pending',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
- Added the required column `updatedAt` to the `Document` table without a default value. This is not possible if the table is not empty.
|
||||
CONSTRAINT "Document_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Document" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "status" TEXT NOT NULL DEFAULT 'pending',
|
||||
ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL;
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"name" TEXT,
|
||||
"password" TEXT NOT NULL,
|
||||
"isAdmin" BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Notification" (
|
||||
@@ -26,12 +41,18 @@ CREATE TABLE "_SharedDocuments" (
|
||||
"B" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "_SharedDocuments_AB_unique" ON "_SharedDocuments"("A", "B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_SharedDocuments_B_index" ON "_SharedDocuments"("B");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Document" ADD CONSTRAINT "Document_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Notification" ADD CONSTRAINT "Notification_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `authorId` on the `Document` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `published` on the `Document` table. All the data in the column will be lost.
|
||||
- You are about to drop the `_SharedDocuments` table. If the table is not empty, all the data it contains will be lost.
|
||||
- Added the required column `sharedWithId` to the `Document` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "Document" DROP CONSTRAINT "Document_authorId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_SharedDocuments" DROP CONSTRAINT "_SharedDocuments_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_SharedDocuments" DROP CONSTRAINT "_SharedDocuments_B_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Document" DROP COLUMN "authorId",
|
||||
DROP COLUMN "published",
|
||||
ADD COLUMN "sharedWithId" INTEGER NOT NULL;
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_SharedDocuments";
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Document" ADD CONSTRAINT "Document_sharedWithId_fkey" FOREIGN KEY ("sharedWithId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -1,9 +1,3 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
||||
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
@@ -13,30 +7,26 @@ datasource db {
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
|
||||
model Document {
|
||||
id Int @id @default(autoincrement())
|
||||
title String
|
||||
content String?
|
||||
published Boolean @default(false)
|
||||
authorId Int
|
||||
author User @relation(fields: [authorId], references: [id])
|
||||
s3Key String
|
||||
status String @default("pending") // pending, uploading, completed, failed
|
||||
sharedWith User[] @relation("SharedDocuments")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
id Int @id @default(autoincrement())
|
||||
title String
|
||||
content String?
|
||||
s3Key String
|
||||
status String @default("pending")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
sharedWithId Int
|
||||
sharedWith User @relation("SharedDocuments", fields: [sharedWithId], references: [id])
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
email String @unique
|
||||
name String?
|
||||
password String
|
||||
isAdmin Boolean @default(false)
|
||||
authoredDocuments Document[] @relation("AuthoredDocuments")
|
||||
sharedDocuments Document[] @relation("SharedDocuments")
|
||||
notifications Notification[]
|
||||
id Int @id @default(autoincrement())
|
||||
email String @unique
|
||||
name String?
|
||||
password String
|
||||
isAdmin Boolean @default(false)
|
||||
sharedDocuments Document[] @relation("SharedDocuments")
|
||||
notifications Notification[]
|
||||
}
|
||||
|
||||
model Notification {
|
||||
@@ -44,8 +34,6 @@ model Notification {
|
||||
message String
|
||||
read Boolean @default(false)
|
||||
userId Int
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
const hashedPassword = await bcrypt.hash('admin123', 10);
|
||||
|
||||
const admin = await prisma.user.upsert({
|
||||
where: { email: 'admin@example.com' },
|
||||
update: {},
|
||||
create: {
|
||||
email: 'admin@example.com',
|
||||
name: 'Admin User',
|
||||
password: hashedPassword,
|
||||
isAdmin: true,
|
||||
},
|
||||
});
|
||||
|
||||
console.log({ admin });
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
@@ -4,22 +4,21 @@ import {
|
||||
Post,
|
||||
Body,
|
||||
Param,
|
||||
Delete,
|
||||
Put,
|
||||
UseInterceptors,
|
||||
UploadedFile,
|
||||
ParseIntPipe,
|
||||
UseGuards,
|
||||
Request,
|
||||
} from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { AdminService } from './admin.service';
|
||||
import { CreateDocumentDto } from '../dto/create-document.dto';
|
||||
//import { CreateDocumentDto } from '../dto/create-document.dto';
|
||||
import { UpdateDocumentDto } from '../dto/update-document.dto';
|
||||
import { AdminGuard } from '../auth/admin.guard';
|
||||
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
|
||||
import { CreateUserDto } from '../dto/create-user.dto';
|
||||
import { S3Service } from 'src/s3/s3.service';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
|
||||
@Controller('admin')
|
||||
@UseGuards(JwtAuthGuard, AdminGuard)
|
||||
@@ -27,27 +26,9 @@ export class AdminController {
|
||||
constructor(
|
||||
private readonly adminService: AdminService,
|
||||
private readonly s3Service: S3Service,
|
||||
private readonly prisma: PrismaService,
|
||||
) {}
|
||||
|
||||
@Post('documents')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
createDocument(
|
||||
@Body() createDocumentDto: CreateDocumentDto,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
) {
|
||||
return this.adminService.createDocument(createDocumentDto, file);
|
||||
}
|
||||
|
||||
// @Post('document')
|
||||
// @UseInterceptors(FileInterceptor('file'))
|
||||
// async createDocument(
|
||||
// @Body() createDocumentDto: CreateDocumentDto,
|
||||
// @UploadedFile() file: Express.Multer.File,
|
||||
// ) {
|
||||
// // The actual file upload is handled by the FileInterceptor
|
||||
// // We just need to pass the file to the service
|
||||
// return this.adminService.createDocument(createDocumentDto, file);
|
||||
// }
|
||||
@Get('documents')
|
||||
getAllDocuments() {
|
||||
return this.adminService.getAllDocuments();
|
||||
@@ -63,16 +44,27 @@ export class AdminController {
|
||||
return this.adminService.updateDocument(id, updateDocumentDto, file);
|
||||
}
|
||||
|
||||
@Delete('documents/:id')
|
||||
async deleteDocument(@Param('id') id: string) {
|
||||
await this.adminService.deleteDocument(+id);
|
||||
return { message: 'Document deleted successfully' };
|
||||
}
|
||||
|
||||
@Get('users')
|
||||
getAllUsers() {
|
||||
return this.adminService.getAllUsers();
|
||||
}
|
||||
@Post('test-document')
|
||||
async testDocumentCreation() {
|
||||
try {
|
||||
const document = await this.prisma.document.create({
|
||||
data: {
|
||||
title: 'Test Document',
|
||||
s3Key: 'test-key',
|
||||
status: 'completed',
|
||||
sharedWithId: 2, // ID of 'pero' user
|
||||
},
|
||||
});
|
||||
return document;
|
||||
} catch (error) {
|
||||
console.error('Test document creation error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@Post('users')
|
||||
async createUser(@Body() createUserDto: CreateUserDto) {
|
||||
@@ -82,9 +74,9 @@ export class AdminController {
|
||||
@Post('documents/:id/share')
|
||||
async shareDocument(
|
||||
@Param('id') id: string,
|
||||
@Body() { userIds }: { userIds: number[] },
|
||||
@Body() { userId }: { userId: number },
|
||||
) {
|
||||
return this.adminService.shareDocument(+id, userIds);
|
||||
return this.adminService.shareDocument(+id, userId);
|
||||
}
|
||||
|
||||
@Put('documents/:id/status')
|
||||
@@ -95,25 +87,33 @@ export class AdminController {
|
||||
return this.adminService.updateDocumentStatus(+id, status);
|
||||
}
|
||||
|
||||
// async uploadDocument(
|
||||
// @UploadedFile() file: Express.Multer.File,
|
||||
// @Body('title') title: string,
|
||||
// @Request() req,
|
||||
// ) {
|
||||
// return this.adminService.uploadDocument(file, title, req.user.userId);
|
||||
// }
|
||||
@Post('documents')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
async uploadDocument(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body('title') title: string,
|
||||
@Body('description') description: number[],
|
||||
@Request() req,
|
||||
@Body('sharedWith') sharedWithId: string,
|
||||
) {
|
||||
return this.adminService.uploadDocument(
|
||||
file,
|
||||
console.log('Received upload request:', {
|
||||
fileExists: !!file,
|
||||
fileSize: file?.size,
|
||||
title,
|
||||
req.user.userId,
|
||||
description,
|
||||
);
|
||||
sharedWithId,
|
||||
});
|
||||
|
||||
try {
|
||||
const document = await this.adminService.uploadDocument(
|
||||
file,
|
||||
title,
|
||||
Number(sharedWithId),
|
||||
);
|
||||
|
||||
console.log('Document created:', document);
|
||||
return document;
|
||||
} catch (error) {
|
||||
console.error('Upload error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@Get('test-s3-connection')
|
||||
async testS3Connection() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { S3Service } from '../s3/s3.service';
|
||||
import { CreateDocumentDto } from '../dto/create-document.dto';
|
||||
//import { CreateDocumentDto } from '../dto/create-document.dto';
|
||||
import { UpdateDocumentDto } from '../dto/update-document.dto';
|
||||
import { CreateUserDto } from '../dto/create-user.dto';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
@@ -13,113 +13,89 @@ export class AdminService {
|
||||
private s3Service: S3Service,
|
||||
) {}
|
||||
|
||||
// async createDocument(
|
||||
// createDocumentDto: CreateDocumentDto,
|
||||
// file: Express.Multer.File,
|
||||
// ) {
|
||||
// const { title, content, clientEmail } = createDocumentDto;
|
||||
|
||||
// console.log('Received createDocumentDto:', createDocumentDto);
|
||||
|
||||
// let author;
|
||||
// if (clientEmail) {
|
||||
// author = await this.prisma.user.findUnique({
|
||||
// where: { email: clientEmail },
|
||||
// });
|
||||
|
||||
// if (!author) {
|
||||
// throw new NotFoundException(`User with email ${clientEmail} not found`);
|
||||
// }
|
||||
// }
|
||||
|
||||
// const s3Key = await this.s3Service.uploadFile(file, 'documents');
|
||||
|
||||
// return this.prisma.document.create({
|
||||
// data: {
|
||||
// title,
|
||||
// content,
|
||||
// s3Key,
|
||||
// ...(author && { author: { connect: { id: author.id } } }),
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
async createDocument(
|
||||
createDocumentDto: CreateDocumentDto,
|
||||
async uploadDocument(
|
||||
file: Express.Multer.File,
|
||||
title: string,
|
||||
sharedWithId: number,
|
||||
) {
|
||||
const { title, content, clientEmail } = createDocumentDto;
|
||||
|
||||
console.log('Received createDocumentDto:', createDocumentDto);
|
||||
|
||||
let authorId: number;
|
||||
if (clientEmail) {
|
||||
const author = await this.prisma.user.findUnique({
|
||||
where: { email: clientEmail },
|
||||
try {
|
||||
// First verify the user exists
|
||||
console.log('Verifying user:', sharedWithId);
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: sharedWithId },
|
||||
});
|
||||
|
||||
if (!author) {
|
||||
throw new NotFoundException(`User with email ${clientEmail} not found`);
|
||||
if (!user) {
|
||||
throw new NotFoundException(`User with ID ${sharedWithId} not found`);
|
||||
}
|
||||
authorId = author.id;
|
||||
} else {
|
||||
// If no clientEmail is provided, we'll use a default admin user
|
||||
// You should replace this with an appropriate default user ID
|
||||
const defaultAdmin = await this.prisma.user.findFirst({
|
||||
where: { isAdmin: true },
|
||||
});
|
||||
if (!defaultAdmin) {
|
||||
throw new NotFoundException('No default admin user found');
|
||||
}
|
||||
authorId = defaultAdmin.id;
|
||||
}
|
||||
|
||||
const s3Key = await this.s3Service.uploadFile(file, 'documents');
|
||||
console.log('Found user:', user);
|
||||
|
||||
return this.prisma.document.create({
|
||||
data: {
|
||||
// Upload file to S3
|
||||
console.log('Uploading file to S3...');
|
||||
const s3Key = await this.s3Service.uploadFile(file, 'documents');
|
||||
console.log('File uploaded to S3:', s3Key);
|
||||
|
||||
console.log('Creating document record with data:', {
|
||||
title,
|
||||
content,
|
||||
s3Key,
|
||||
author: { connect: { id: authorId } },
|
||||
},
|
||||
});
|
||||
}
|
||||
sharedWithId,
|
||||
});
|
||||
|
||||
// async getAllDocuments() {
|
||||
// return this.prisma.document.findMany({
|
||||
// include: {
|
||||
// sharedWith: {
|
||||
// select: {
|
||||
// id: true,
|
||||
// name: true,
|
||||
// email: true,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
const document = await this.prisma.document.create({
|
||||
data: {
|
||||
title,
|
||||
s3Key,
|
||||
status: 'completed',
|
||||
sharedWithId,
|
||||
},
|
||||
include: {
|
||||
sharedWith: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
console.log('Created document:', document);
|
||||
return document;
|
||||
} catch (error) {
|
||||
console.error('Error in uploadDocument:', error);
|
||||
if (error.code === 'P2002') {
|
||||
console.error('Unique constraint violation');
|
||||
}
|
||||
if (error.code === 'P2003') {
|
||||
console.error('Foreign key constraint violation');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async getAllDocuments() {
|
||||
return this.prisma.document.findMany({
|
||||
include: {
|
||||
author: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
try {
|
||||
const documents = await this.prisma.document.findMany({
|
||||
include: {
|
||||
sharedWith: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
sharedWith: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
console.log('Retrieved documents with shared users:', documents);
|
||||
return documents;
|
||||
} catch (error) {
|
||||
console.error('Error fetching documents:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateDocument(
|
||||
@@ -149,57 +125,6 @@ export class AdminService {
|
||||
},
|
||||
});
|
||||
}
|
||||
async uploadDocument(
|
||||
file: Express.Multer.File,
|
||||
title: string,
|
||||
userId: number,
|
||||
sharedWith: number[],
|
||||
) {
|
||||
let s3Key;
|
||||
try {
|
||||
s3Key = await this.s3Service.uploadFile(file, 'documents');
|
||||
|
||||
// Log the sharedWith array to verify the data
|
||||
console.log('Sharing document with users:', sharedWith);
|
||||
|
||||
const document = await this.prisma.document.create({
|
||||
data: {
|
||||
title,
|
||||
authorId: userId,
|
||||
s3Key,
|
||||
status: 'completed',
|
||||
sharedWith: {
|
||||
connect: sharedWith.map((id) => ({ id })),
|
||||
},
|
||||
},
|
||||
include: {
|
||||
sharedWith: true, // Include this to verify the relation was created
|
||||
},
|
||||
});
|
||||
|
||||
console.log('Created document:', document);
|
||||
return document;
|
||||
} catch (error) {
|
||||
console.error('Error in uploadDocument:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteDocument(id: number) {
|
||||
const document = await this.prisma.document.findUnique({
|
||||
where: { id },
|
||||
select: { s3Key: true },
|
||||
});
|
||||
if (document?.s3Key) {
|
||||
await this.s3Service.deleteFile(document.s3Key);
|
||||
}
|
||||
|
||||
return this.prisma.document.delete({ where: { id } });
|
||||
}
|
||||
|
||||
async getAllUsers() {
|
||||
return this.prisma.user.findMany();
|
||||
}
|
||||
|
||||
async createUser(createUserDto: CreateUserDto) {
|
||||
const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
|
||||
@@ -211,25 +136,22 @@ export class AdminService {
|
||||
});
|
||||
}
|
||||
|
||||
async shareDocument(documentId: number, userIds: number[]) {
|
||||
const document = await this.prisma.document.update({
|
||||
async shareDocument(documentId: number, userId: number) {
|
||||
return this.prisma.document.update({
|
||||
where: { id: documentId },
|
||||
data: {
|
||||
sharedWithId: userId,
|
||||
},
|
||||
include: {
|
||||
sharedWith: {
|
||||
connect: userIds.map((id: number) => ({ id })),
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Create notifications for shared users
|
||||
await this.prisma.notification.createMany({
|
||||
data: userIds.map((userId: number) => ({
|
||||
userId,
|
||||
message: `A new document "${document.title}" has been shared with you.`,
|
||||
})),
|
||||
});
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
async updateDocumentStatus(documentId: number, status: string) {
|
||||
@@ -239,100 +161,6 @@ export class AdminService {
|
||||
});
|
||||
}
|
||||
|
||||
// async uploadDocument(
|
||||
// file: Express.Multer.File,
|
||||
// title: string,
|
||||
// userId: number,
|
||||
// ) {
|
||||
// try {
|
||||
// // First create document with pending status
|
||||
// const document = await this.prisma.document.create({
|
||||
// data: {
|
||||
// title,
|
||||
// authorId: userId,
|
||||
// status: 'pending',
|
||||
// s3Key: '', // Temporary empty key
|
||||
// },
|
||||
// });
|
||||
|
||||
// // Update status to uploading
|
||||
// await this.prisma.document.update({
|
||||
// where: { id: document.id },
|
||||
// data: { status: 'uploading' },
|
||||
// });
|
||||
|
||||
// // Upload to S3
|
||||
// const s3Key = await this.s3Service.uploadFile(file, 'documents');
|
||||
|
||||
// // Update document with s3Key and completed status
|
||||
// return this.prisma.document.update({
|
||||
// where: { id: document.id },
|
||||
// data: {
|
||||
// s3Key,
|
||||
// status: 'completed',
|
||||
// },
|
||||
// });
|
||||
// } catch (error) {
|
||||
// // If anything fails, update status to failed
|
||||
// const document = await this.prisma.document.findFirst({
|
||||
// where: { title, authorId: userId },
|
||||
// });
|
||||
// if (document) {
|
||||
// await this.prisma.document.update({
|
||||
// where: { id: document.id },
|
||||
// data: { status: 'failed' },
|
||||
// });
|
||||
// }
|
||||
// throw error;
|
||||
// }
|
||||
// }
|
||||
|
||||
// problem whith upload status writing to db, i will fix it later
|
||||
|
||||
// async uploadDocument(
|
||||
// file: Express.Multer.File,
|
||||
// title: string,
|
||||
// userId: number,
|
||||
// sharedWith: number[],
|
||||
// ) {
|
||||
// let s3Key;
|
||||
// try {
|
||||
// // First upload to S3
|
||||
// s3Key = await this.s3Service.uploadFile(file, 'documents');
|
||||
|
||||
// // Then create document with completed status and s3Key
|
||||
// const document = await this.prisma.document.create({
|
||||
// data: {
|
||||
// title,
|
||||
// authorId: userId,
|
||||
// s3Key,
|
||||
// status: 'completed', // Set status to completed immediately after successful upload
|
||||
// sharedWith: {
|
||||
// connect: sharedWith.map((id: number) => ({ id })),
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
|
||||
// return document;
|
||||
// } catch (error) {
|
||||
// // Create document with failed status if upload fails
|
||||
// if (title && userId) {
|
||||
// await this.prisma.document.create({
|
||||
// data: {
|
||||
// title,
|
||||
// authorId: userId,
|
||||
// s3Key: s3Key || '',
|
||||
// status: 'failed',
|
||||
// sharedWith: {
|
||||
// connect: sharedWith.map((id: number) => ({ id })),
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// throw error;
|
||||
// }
|
||||
// }
|
||||
|
||||
async getDocumentUrl(documentId: number) {
|
||||
const document = await this.prisma.document.findUnique({
|
||||
where: { id: documentId },
|
||||
@@ -342,4 +170,34 @@ export class AdminService {
|
||||
}
|
||||
return this.s3Service.getFileUrl(document.s3Key);
|
||||
}
|
||||
async getUserWithDocuments(userId: number) {
|
||||
return this.prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
sharedDocuments: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getAllUsers() {
|
||||
try {
|
||||
const users = await this.prisma.user.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
isAdmin: true,
|
||||
sharedDocuments: true,
|
||||
},
|
||||
});
|
||||
console.log('All users:', users);
|
||||
return users;
|
||||
} catch (error) {
|
||||
console.error('Error fetching users:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { PrismaService } from './prisma/prisma.service';
|
||||
import { PrismaModule } from './prisma/prisma.module';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { AuthController } from './auth/auth.controller';
|
||||
import { DocumentsController } from './documents/documents.controller';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -32,7 +33,7 @@ import { AuthController } from './auth/auth.controller';
|
||||
S3Module,
|
||||
PrismaModule,
|
||||
],
|
||||
controllers: [AppController, AuthController],
|
||||
controllers: [AppController, AuthController, DocumentsController],
|
||||
providers: [
|
||||
AppService,
|
||||
UploadService,
|
||||
|
||||
@@ -10,6 +10,6 @@ export class ClientController {
|
||||
|
||||
@Get('documents')
|
||||
async getClientDocuments(@User() user) {
|
||||
return this.clientService.getClientDocuments(user.id);
|
||||
return this.clientService.getDocuments(user.id);
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,26 @@ import { PrismaService } from '../prisma/prisma.service';
|
||||
export class ClientService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async getClientDocuments(userId: string) {
|
||||
// async getClientDocuments(userId: string) {
|
||||
// return this.prisma.document.findMany({
|
||||
// where: {
|
||||
// authorId: Number(userId),
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
async getDocuments(userId: string) {
|
||||
return this.prisma.document.findMany({
|
||||
where: {
|
||||
authorId: Number(userId),
|
||||
sharedWithId: Number(userId),
|
||||
},
|
||||
include: {
|
||||
sharedWith: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { DocumentsController } from './documents.controller';
|
||||
|
||||
describe('DocumentsController', () => {
|
||||
let controller: DocumentsController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [DocumentsController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<DocumentsController>(DocumentsController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Controller, Get, Param } from '@nestjs/common';
|
||||
import { DocumentsService } from './documents.service';
|
||||
|
||||
@Controller('documents')
|
||||
export class DocumentsController {
|
||||
constructor(private readonly documentsService: DocumentsService) {}
|
||||
@Get('shared/:userId')
|
||||
async getSharedDocuments(@Param('userId') userId: string) {
|
||||
console.log('userId', userId);
|
||||
return this.documentsService.getClientDocuments(parseInt(userId));
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,33 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { Document } from '@prisma/client';
|
||||
//import { Document } from '@prisma/client';
|
||||
|
||||
@Injectable()
|
||||
export class DocumentsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async findAllForClient(clientId: number): Promise<Document[]> {
|
||||
async getClientDocuments(clientId: number) {
|
||||
// return this.prisma.document.findMany({
|
||||
// where: {
|
||||
// sharedWithId: clientId,
|
||||
// },
|
||||
// include: {
|
||||
// sharedWith: {
|
||||
// select: {
|
||||
// id: true,
|
||||
// name: true,
|
||||
// email: true,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
return this.prisma.document.findMany({
|
||||
where: { authorId: clientId },
|
||||
where: {
|
||||
sharedWithId: clientId,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user