Skip to content
1,425 changes: 693 additions & 732 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand --config ./test/jest.json"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.893.0",
"@aws-sdk/client-s3": "^3.908.0",
"@aws-sdk/client-sesv2": "^3.890.0",
"@nestjs/common": "^11.1.6",
"@nestjs/config": "^4.0.2",
Expand Down
12 changes: 6 additions & 6 deletions src/entities/collaboration-request.entity.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
CreateDateColumn,
Entity,
JoinColumn,
ManyToOne,
OneToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { Profile } from './profile.entity';
import { Idea } from './idea.entity';
import { Chat } from './chat.entity';
import { Idea } from './idea.entity';
import { Profile } from './profile.entity';

export enum CollaborationRequestStatus {
PENDING = 'Pending',
Expand Down Expand Up @@ -72,7 +72,7 @@ export class CollaborationRequest {
collaborationRequest.message = this.message;
collaborationRequest.ideaTitle = this.idea.title;
collaborationRequest.requesterName = !isRequester
? this.requester.displayName
? (this.requester?.displayName ?? null)
: null;
return collaborationRequest;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@
import type { RequestWithUserData } from 'src/jwt/jwt.strategy';
import { Protected } from 'src/shared/decorators/protected.decorator';
import {
CollaborationRequestAlreadyApproved,
IdeaNotFound,
PendingCollaborationRequestAlreadyExists,
UserAlreadyMemberOfTheProject,
YouCannotRequestCollaborationForYourOwnIdea,
} from 'src/shared/errors';
import { safeSave } from 'src/shared/utils/safe-save.util';
import { Repository } from 'typeorm';
import { In, Repository } from 'typeorm';
import { CollaborationRequestInput } from './collaboration-request.dto';

@Controller('/collaboration-request')
Expand All @@ -53,26 +55,46 @@
@Request() { user: { userProfileId } }: RequestWithUserData,
@Body() { message, ideaId }: CollaborationRequestInput,
): Promise<CollaborationRequest> {
const collaborationRequest =
await this.collaborationRequestRepository.findOne({
where: {
requesterId: userProfileId,
ideaId,
status: CollaborationRequestStatus.PENDING,
},
});
if (collaborationRequest) {
throw new PendingCollaborationRequestAlreadyExists();
const statusesToCheck = [
CollaborationRequestStatus.PENDING,
CollaborationRequestStatus.APPROVED,
];

const existingRequest = await this.collaborationRequestRepository.findOne({
where: {
requesterId: userProfileId,
ideaId,
status: In(statusesToCheck),
},
});
if (existingRequest) {
if (existingRequest.status === CollaborationRequestStatus.PENDING) {
throw new PendingCollaborationRequestAlreadyExists();
}

if (existingRequest.status === CollaborationRequestStatus.APPROVED) {
throw new CollaborationRequestAlreadyApproved();
}
}

const idea = await this.ideaRepository.findOne({
where: { id: ideaId },
relations: ['project', 'project.members'],
});

if (!idea) throw new IdeaNotFound();

if (idea.authorId === userProfileId) {
throw new YouCannotRequestCollaborationForYourOwnIdea();
}

if (
idea.project &&
idea.project.members?.some((member) => member.id === userProfileId)

Check warning on line 93 in src/features/collaboration-requests/collaboration-request/v1/collaboration-request.controller.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=G4mix_back-end&issues=AZrVnMouzMEPjGhdOzLW&open=AZrVnMouzMEPjGhdOzLW&pullRequest=13
) {
throw new UserAlreadyMemberOfTheProject();
}

const savedRequest = await safeSave(this.collaborationRequestRepository, {
ideaId,
message,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ import {
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { Comment } from 'src/entities/comment.entity';
import { IdeaNotFound } from 'src/shared/errors';
import { Idea } from 'src/entities/idea.entity';

@Controller('/comment')
export class GetAllCommentsController {
constructor(
@InjectRepository(Comment)
private readonly commentRepository: Repository<Comment>,
@InjectRepository(Idea)
private readonly ideaRepository: Repository<Idea>,
) {}
readonly logger = new Logger(this.constructor.name);

Expand All @@ -32,6 +36,14 @@ export class GetAllCommentsController {
@Request() req: RequestWithUserData,
@Query() { quantity, page, ideaId, parentCommentId }: GetAllCommentsInput,
): Promise<GetAllCommentsOutput> {
if (!ideaId) throw new IdeaNotFound();

const idea = await this.ideaRepository.findOne({
where: { id: ideaId },
});

if (!idea) throw new IdeaNotFound();

const qb = this.commentRepository
.createQueryBuilder('comment')
.leftJoinAndSelect('comment.author', 'author')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class GetAllCommentsInput {
@IsOptional()
quantity: number = 10;

@IsUUID()
@IsUUID(undefined, { message: 'INVALID_IDEA_ID' })
ideaId: string;

@IsOptional()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { generateTestJwt } from 'test/jwt-helper';
import { createTestIdea, createTestUser } from 'test/test-helpers';
import request from 'supertest';

describe('/v1/comment (GET)', () => {
it('should return 200 and all comments for an idea', async () => {
const user1 = await createTestUser(
'testuser',
'test@example.com',
'password123',
);

const idea = await createTestIdea(
'Test Idea Title',
'This is the content of the test idea',
user1.profileId,
[], // no comments at creation
);

const user2 = await createTestUser(
'testuser2',
'test2@example.com',
'password1234',
);
const tokenUser2 = generateTestJwt({
sub: user2.id,
userProfileId: user2.profileId,
});
const user3 = await createTestUser(
'testuser3',
'test3@example.com',
'password12345',
);
const tokenUser3 = generateTestJwt({
sub: user3.id,
userProfileId: user3.profileId,
});

await request(app.getHttpServer())
.post('/v1/comment')
.set('Authorization', `Bearer ${tokenUser2}`)
.send({
content: 'Comment',
ideaId: idea.id,
});

// 1 comentário do user3
await request(app.getHttpServer())
.post('/v1/comment')
.set('Authorization', `Bearer ${tokenUser3}`)
.send({
content: 'Comment 2',
ideaId: idea.id,
});

const response = await request(app.getHttpServer()).get(
`/v1/comment?ideaId=${idea.id}`,
);

expect(response.status).toEqual(200);
expect(response.body.data.length).toEqual(2);
});

it('should return 400 when idea id is invalid', async () => {
const ideaId = '1';
const response = await request(app.getHttpServer()).get(
`/v1/comment?ideaId=${ideaId}`,
);

expect(response.status).toBe(400);
expect(response.body.data).toBeUndefined();
expect(response.body.message).toContain('INVALID_IDEA_ID');
});

it('should return 404 when ideaId does not exist', async () => {
const ideaId = '1e9c20a4-3f8d-4b71-8c0e-92a15f0b6d2c';
const response = await request(app.getHttpServer()).get(
`/v1/comment?ideaId=${ideaId}`,
);

expect(response.status).toBe(404);
expect(response.body.message).toContain('IDEA_NOT_FOUND');
});
});
Loading