Skip to content

Commit

Permalink
Merge pull request #2 from fga-eps-mds/feat#75/gerenciar-jornada
Browse files Browse the repository at this point in the history
[feat#75]-Gerenciar Jornada/Trilha/Conteudo
  • Loading branch information
DaviMatheus authored Aug 18, 2024
2 parents a63e0e8 + c858f39 commit 19bc9b1
Show file tree
Hide file tree
Showing 25 changed files with 1,384 additions and 257 deletions.
3 changes: 3 additions & 0 deletions .env.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MONGODB_URI=
USER_SERVICE_URL=
AUTH_SERVICE_URL=
16 changes: 6 additions & 10 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import type { Config } from 'jest';
import * as dotenv from 'dotenv';

dotenv.config();

dotenv.config();
const config: Config = {
moduleFileExtensions: ['js', 'json', 'ts'],
rootDir: './test',
testRegex: '.*\\.spec\\.ts$',
transform: {
'^.+\\.(t|j)s$': 'ts-jest',
},
collectCoverageFrom: ['**/*.(t|j)s'],
coverageDirectory: '../coverage',
preset: 'ts-jest',
testEnvironment: 'node',
reporters: [
'default',
Expand All @@ -23,6 +15,10 @@ const config: Config = {
},
],
],
moduleNameMapper: {
'^src/(.*)$': '<rootDir>/src/$1',
},
setupFiles: ['dotenv/config'],
};

export default config;
4 changes: 4 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { MongooseModule } from '@nestjs/mongoose';
import { HttpModule } from '@nestjs/axios';
import { ContentModule } from './content/content.module';
import * as Joi from 'joi';
import { JourneyModule } from './journey/journey.module';
import { TrailModule } from './trail/trail.module';

@Module({
imports: [
Expand All @@ -23,6 +25,8 @@ import * as Joi from 'joi';
}),
HttpModule,
ContentModule,
JourneyModule,
TrailModule,
],
controllers: [],
providers: [],
Expand Down
58 changes: 27 additions & 31 deletions src/content/content.controller.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,53 @@
import {
Controller,
Get,
Post,
Body,
Param,
Put,
Req,
UnauthorizedException,
Get,
Patch,
Delete,
Param,
Body,
NotFoundException,
} from '@nestjs/common';
import { ContentService } from './content.service';
import { CreateContentDto } from './dtos/create-content.dto';
import { Request } from 'express';
import { Content } from './content.schema';

@Controller('contents')
export class ContentController {
constructor(private readonly contentService: ContentService) {}

@Post()
async create(
@Body() createContentDto: CreateContentDto,
@Req() req: Request,
) {
const authHeader = req.headers.authorization as string;
const token = authHeader?.split(' ')[1];

if (!token) {
throw new UnauthorizedException('Token not found');
async createContent(
@Body() body: { title: string; content: string; trailId: string },
): Promise<Content> {
const { title, content, trailId } = body;

if (!title || !content || !trailId) {
throw new NotFoundException('Title, content, and trailId are required');
}

return this.contentService.create(createContentDto, token);
return this.contentService.createContent(title, content, trailId);
}

@Get()
async findAll() {
return this.contentService.findAll();
@Get(':id')
async findContentById(@Param('id') id: string): Promise<Content> {
return this.contentService.findContentById(id);
}

@Get(':id')
async findById(@Param('id') id: string) {
return this.contentService.findById(id);
@Get()
async findAllContents(): Promise<Content[]> {
return this.contentService.findAllContents();
}

@Put(':id')
async update(
@Patch(':id')
async updateContent(
@Param('id') id: string,
@Body() updateContentDto: CreateContentDto,
) {
return this.contentService.update(id, updateContentDto);
@Body() updateData: Partial<Content>,
): Promise<Content> {
return this.contentService.updateContent(id, updateData);
}

@Delete(':id')
async delete(@Param('id') id: string) {
return this.contentService.delete(id);
async deleteContent(@Param('id') id: string): Promise<void> {
return this.contentService.deleteContent(id);
}
}
7 changes: 4 additions & 3 deletions src/content/content.module.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Module } from '@nestjs/common';
import { Module, forwardRef } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { ContentSchema } from './content.schema';
import { ContentService } from './content.service';
import { ContentController } from './content.controller';
import { HttpModule } from '@nestjs/axios';
import { TrailModule } from '../trail/trail.module';

@Module({
imports: [
HttpModule,
MongooseModule.forFeature([{ name: 'Content', schema: ContentSchema }]),
forwardRef(() => TrailModule),
],
providers: [ContentService],
controllers: [ContentController],
exports: [ContentService],
})
export class ContentModule {}
16 changes: 8 additions & 8 deletions src/content/content.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import * as mongoose from 'mongoose';
export const ContentSchema = new mongoose.Schema(
{
title: { type: String, required: true },
body: { type: String, required: true },
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
trail: { type: mongoose.Schema.Types.ObjectId, ref: 'Trail' },
journey: { type: mongoose.Schema.Types.ObjectId, ref: 'Journey' },
content: { type: String, required: true },
trail: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Trail',
required: true,
},
},
{ timestamps: true, collection: 'contents' },
);

export interface Content extends mongoose.Document {
title: string;
body: string;
user: mongoose.Schema.Types.ObjectId;
trail?: mongoose.Schema.Types.ObjectId;
journey?: mongoose.Schema.Types.ObjectId;
content: string;
trail: mongoose.Schema.Types.ObjectId;
}
83 changes: 31 additions & 52 deletions src/content/content.service.ts
Original file line number Diff line number Diff line change
@@ -1,92 +1,71 @@
import {
Injectable,
Logger,
NotFoundException,
UnauthorizedException,
} from '@nestjs/common';
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Content } from './content.schema';
import { CreateContentDto } from './dtos/create-content.dto';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
import { Trail } from '../trail/trail.schema';
import { TrailService } from '../trail/trail.service';

@Injectable()
export class ContentService {
private readonly logger = new Logger(ContentService.name);

constructor(
@InjectModel('Content') private readonly contentModel: Model<Content>,
private readonly httpService: HttpService,
@InjectModel('Trail') private readonly trailModel: Model<Trail>,
private readonly trailService: TrailService,
) {}

async create(
createContentDto: CreateContentDto,
token: string,
async createContent(
title: string,
content: string,
trailId: string,
): Promise<Content> {
const userId = await this.validateTokenAndGetUserId(token);

this.logger.log(`User ID from token: ${userId}`);

if (!userId) {
throw new UnauthorizedException('Invalid token');
const trailExists = await this.trailModel.findById(trailId).exec();
if (!trailExists) {
throw new NotFoundException(`Trail with ID ${trailId} not found`);
}

const newContent = new this.contentModel({
...createContentDto,
user: userId,
title,
content,
trail: trailId,
});
return newContent.save();
}

async validateTokenAndGetUserId(token: string): Promise<string | null> {
try {
this.logger.log(`Validating token: ${token}`);
const response = await firstValueFrom(
this.httpService.get(`${process.env.AUTH_SERVICE_URL}/validate-token`, {
headers: { Authorization: `Bearer ${token}` },
}),
);
this.logger.log(
`Token validation response: ${JSON.stringify(response.data)}`,
);
return response.data.userPayload?.id || null;
} catch (err) {
this.logger.error(`Token validation failed: ${err.message}`);
return null;
}
}
await this.trailService.addContentToTrail(
trailId,
newContent._id.toString(),
);

async findAll(): Promise<Content[]> {
return this.contentModel.find().exec();
return newContent.save();
}

async findById(id: string): Promise<Content> {
async findContentById(id: string): Promise<Content> {
const content = await this.contentModel.findById(id).exec();
if (!content) {
throw new NotFoundException(`Content with ID ${id} not found`);
}
return content;
}

async update(
async findAllContents(): Promise<Content[]> {
return this.contentModel.find().exec();
}

async updateContent(
id: string,
updateContentDto: CreateContentDto,
updateData: Partial<Content>,
): Promise<Content> {
const content = await this.contentModel
.findByIdAndUpdate(id, updateContentDto, { new: true })
.findByIdAndUpdate(id, updateData, { new: true })
.exec();
if (!content) {
throw new NotFoundException(`Content with ID ${id} not found`);
}
return content;
}

async delete(id: string): Promise<Content> {
const content = await this.contentModel.findByIdAndDelete(id).exec();
if (!content) {
async deleteContent(id: string): Promise<void> {
const result = await this.contentModel.findByIdAndDelete(id).exec();
if (!result) {
throw new NotFoundException(`Content with ID ${id} not found`);
}
return content;
}
}
18 changes: 6 additions & 12 deletions src/content/dtos/create-content.dto.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import { IsString, IsOptional, IsMongoId } from 'class-validator';
import { IsString, IsNotEmpty, IsMongoId } from 'class-validator';

export class CreateContentDto {
@IsString()
@IsNotEmpty()
title: string;

@IsString()
body: string;
@IsNotEmpty()
content: string;

@IsOptional()
@IsMongoId()
user?: string;

@IsOptional()
@IsMongoId()
trail?: string;

@IsOptional()
@IsMongoId()
journey?: string;
@IsNotEmpty()
trail: string;
}
13 changes: 13 additions & 0 deletions src/journey/dtos/create-journey.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { IsString, IsOptional, IsMongoId } from 'class-validator';

export class CreateJourneyDto {
@IsString()
title: string;

@IsString()
description: string;

@IsOptional()
@IsMongoId()
user?: string;
}
Loading

0 comments on commit 19bc9b1

Please sign in to comment.