Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions semana22/projeto-Lama/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
roots: ["<rootDir>/tests"],
transform: {
"^.+\\.tsx?$": "ts-jest",
},
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
};
38 changes: 38 additions & 0 deletions semana22/projeto-Lama/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "lama-template",
"version": "1.0.0",
"description": "Template para o projeto LAMA",
"main": "index.js",
"scripts": {
"test": "clear && echo \"Starting tests ...\" && jest",
"start": "clear && ts-node ./src/index.ts"
},
"keywords": [
"api",
"lama"
],
"author": "https://github.com/vinnivso",
"dependencies": {
"bcryptjs": "^2.4.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"knex": "^0.21.2",
"moment": "^2.27.0",
"mysql": "^2.18.1",
"uuid": "^8.2.0",
"jest": "^27.0.4"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/express": "^4.17.7",
"@types/jsonwebtoken": "^8.5.0",
"@types/knex": "^0.16.1",
"@types/uuid": "^8.0.0",
"typescript": "^4.3.4",
"@types/jest": "^26.0.23",
"ts-node-dev": "^1.1.6",
"@types/node": "^15.12.4",
"ts-jest": "^27.0.3"
}
}
45 changes: 45 additions & 0 deletions semana22/projeto-Lama/src/business/BandBusiness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { BandDatabase } from "../data/BandDatabase";
import { InvalidInputError } from "../error/InvalidInputError";
import { UnauthorizedError } from "../error/UnauthorizedError";
import { Band, BandInputDTO } from "../model/Band";
import { UserRole } from "../model/User";
import { Authenticator } from "../services/Authenticator";
import { IdGenerator } from "../services/IdGenerator";

export class BandBusiness {
constructor(
private bandDatabase:BandDatabase,
private idGenerator:IdGenerator,
private authenticator:Authenticator
){}
async registerBand(input:BandInputDTO, token: string) {
//Primeiro pego o meu token para saber se é NORMAL ou ADMIN.
const tokenData = this.authenticator.getData(token)

//Verificação de Role
if(tokenData.role !== UserRole.ADMIN) {
throw new UnauthorizedError("Only ADMINS can access this feature!")
}

//Verificação de Input
if(!input.name || !input.mainGenre || !input.responsible) {
throw new InvalidInputError("Invalid input to register band.")
}

//Criação da band, estou passando os dados do input e inserindo a criação de uma id.
await this.bandDatabase.createBand(
Band.toBand({
...input,
id:this.idGenerator.generate()
})!
)
}

async getBandDetailByIrOrName(input: string): Promise<Band> {
if(!input){
throw new InvalidInputError("Invalid input to getBandDetails")
}

return this.bandDatabase.getBandByIdOrNameOrFail(input)
}
}
72 changes: 72 additions & 0 deletions semana22/projeto-Lama/src/business/ShowBusiness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { BandDatabase } from "../data/BandDatabase";
import { ShowDatabase } from "../data/ShowDatabase";
import { InvalidInputError } from "../error/InvalidInputError";
import { NotFoundError } from "../error/NotFoundError";
import { UnauthorizedError } from "../error/UnauthorizedError";
import { Show, ShowInputDTO, WeekDay } from "../model/Show";
import { UserRole } from "../model/User";
import { Authenticator } from "../services/Authenticator";
import { IdGenerator } from "../services/IdGenerator";

export class ShowBusiness {
constructor(
private showDatabase: ShowDatabase,
private bandDatabase: BandDatabase,
private idGenerator: IdGenerator,
private authenticator: Authenticator,
){}

async createShow(input: ShowInputDTO, token: string) {
//Verificando se o user é ADMIN
const tokenData = this.authenticator.getData(token)
if(tokenData.role !== UserRole.ADMIN) {
throw new UnauthorizedError(`Only ADMINS can access this feature`)
}

//Validando o INPUT
if(!input.bandId || !input.weekDay || !input.startTime || !input.endTime) {
throw new InvalidInputError(`Invalid INPUT to create Show`)
}

//Validando os horários com base no enunciado
if(input.startTime < 8 || input.endTime > 23 || input.startTime >= input.endTime) {
throw new InvalidInputError(`Invalid TIMES to create Show`)
}

//Verificando se o valor da hora inserida é INTEIRO
if(!Number.isInteger(input.startTime) || !Number.isInteger(input.endTime)) {
throw new InvalidInputError(`Invalid INT TIMES to create Show`)
}

//Verificando se o ID da BANDA é válido
const band = await this.bandDatabase.getBandByIdOrNameOrFail(input.bandId)

//Se a banda não existir
if(!band) {
throw new NotFoundError(`Band not found in DATABASE`)
}

//Validação de Concomitância
const registeredShows = await this.showDatabase.getShowsByTimes(input.weekDay, input.startTime, input.endTime)
if(registeredShows.length) {
throw new InvalidInputError(`No more shows can be created at this TIMES`)
}

//Nenhuma outra VALIDAÇÃO, então vamos criar o SHOW
await this.showDatabase.createShow(
Show.toShow({
...input,
id: this.idGenerator.generate()
})
)
}

async getShowsByWeekDay(weekDay: WeekDay) {
if(!weekDay) {
throw new InvalidInputError(`Invalid INPUT to get Shows By Week Day`)
}

const shows = await this.showDatabase.getShowsByWeekDayOrFail(weekDay)
return {result:shows}
}
}
43 changes: 43 additions & 0 deletions semana22/projeto-Lama/src/business/UserBusiness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { UserInputDTO, LoginInputDTO } from "../model/User";
import { UserDatabase } from "../data/UserDatabase";
import { IdGenerator } from "../services/IdGenerator";
import { HashManager } from "../services/HashManager";
import { Authenticator } from "../services/Authenticator";

export class UserBusiness {

async createUser(user: UserInputDTO) {

const idGenerator = new IdGenerator();
const id = idGenerator.generate();

const hashManager = new HashManager();
const hashPassword = await hashManager.hash(user.password);

const userDatabase = new UserDatabase();
await userDatabase.createUser(id, user.email, user.name, hashPassword, user.role);

const authenticator = new Authenticator();
const accessToken = authenticator.generateToken({ id, role: user.role });

return accessToken;
}

async getUserByEmail(user: LoginInputDTO) {

const userDatabase = new UserDatabase();
const userFromDB = await userDatabase.getUserByEmail(user.email);

const hashManager = new HashManager();
const hashCompare = await hashManager.compare(user.password, userFromDB.getPassword());

const authenticator = new Authenticator();
const accessToken = authenticator.generateToken({ id: userFromDB.getId(), role: userFromDB.getRole() });

if (!hashCompare) {
throw new Error("Invalid Password!");
}

return accessToken;
}
}
52 changes: 52 additions & 0 deletions semana22/projeto-Lama/src/controller/BandController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import express from "express";
import { BandBusiness } from "../business/BandBusiness";
import { BandDatabase } from "../data/BandDatabase";
import { BaseDatabase } from "../data/BaseDatabase";
import { BandInputDTO } from "../model/Band";
import { Authenticator } from "../services/Authenticator";
import { IdGenerator } from "../services/IdGenerator";

export class BandController {
//Será um método async, pois precisarei criar alguma coisa no banco, ou seja, vai rolar uma requisição de comunicação com o DB.
async registerBand(req:express.Request, res: express.Response){
try {
const input: BandInputDTO = {
name: req.body.name,
mainGenre: req.body.mainGenre,
responsible:req.body.responsible
}

const bandBusiness = new BandBusiness(
new BandDatabase,
new IdGenerator,
new Authenticator
)
await bandBusiness.registerBand(input, req.headers.authorization as string)
res.sendStatus(200)
} catch (error:any) {
res.status(error.customErrorCode || 400).send({message:error.message})
} finally {
await BaseDatabase.destroyConnection()
}
}

async getBandDetail(req:express.Request, res: express.Response){
try {
//(req.query.id ?? req.query.name),caso a requisição de query.id seja nula, então eu vou receber query.name. Os "??" se chama operador nullish.
const input = (req.query.id ?? req.query.name) as string

const bandBusiness = new BandBusiness(
new BandDatabase,
new IdGenerator,
new Authenticator
)

const band = await bandBusiness.getBandDetailByIrOrName(input)
res.status(200).send(band)
} catch (error:any) {
res.status(error.customErrorCode || 400).send({message:error.message})
} finally {
await BaseDatabase.destroyConnection()
}
}
}
60 changes: 60 additions & 0 deletions semana22/projeto-Lama/src/controller/ShowController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import express from "express";
import { ShowBusiness } from "../business/ShowBusiness";
import { BandDatabase } from "../data/BandDatabase";
import { BaseDatabase } from "../data/BaseDatabase";
import { ShowDatabase } from "../data/ShowDatabase";
import { Show, ShowInputDTO } from "../model/Show";
import { Authenticator } from "../services/Authenticator";
import { IdGenerator } from "../services/IdGenerator";

export class ShowController {
async createShow(req:express.Request, res:express.Response) {
try {
const weekDay = Show.toWeekDayEnum(req.body.weekDay)

const input: ShowInputDTO = {
weekDay,
bandId: req.body.bandId,
startTime: req.body.starTime,
endTime: req.body.endTime
}
const showBusiness = new ShowBusiness(
new ShowDatabase,
new BandDatabase,
new IdGenerator,
new Authenticator
)
await showBusiness.createShow(input, req.headers.authorization as string)
res.sendStatus(200)


} catch (error:any) {
res.status(error.customErrorCode || 400).send({message:error.message})


} finally {
await BaseDatabase.destroyConnection()
}
}

async getShowsByWeekDay(req:express.Request, res:express.Response) {
try {
const weekDay = Show.toWeekDayEnum(req.query.weekDay as string)
const showBusiness = new ShowBusiness(
new ShowDatabase,
new BandDatabase,
new IdGenerator,
new Authenticator
)
const shows = await showBusiness.getShowsByWeekDay(weekDay)
res.status(200).send({shows})

} catch (error:any) {
res.status(error.customErrorCode || 400).send({message:error.message})


} finally {
await BaseDatabase.destroyConnection()
}
}
}
50 changes: 50 additions & 0 deletions semana22/projeto-Lama/src/controller/UserController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Request, Response } from "express";
import { UserInputDTO, LoginInputDTO} from "../model/User";
import { UserBusiness } from "../business/UserBusiness";
import { BaseDatabase } from "../data/BaseDatabase";

export class UserController {
async signup(req: Request, res: Response) {
try {

const input: UserInputDTO = {
email: req.body.email,
name: req.body.name,
password: req.body.password,
role: req.body.role
}

const userBusiness = new UserBusiness();
const token = await userBusiness.createUser(input);

res.status(200).send({ token });

} catch (error:any) {
res.status(400).send({ error: error.message });
}

await BaseDatabase.destroyConnection();
}

async login(req: Request, res: Response) {

try {

const loginData: LoginInputDTO = {
email: req.body.email,
password: req.body.password
};

const userBusiness = new UserBusiness();
const token = await userBusiness.getUserByEmail(loginData);

res.status(200).send({ token });

} catch (error:any) {
res.status(400).send({ error: error.message });
}

await BaseDatabase.destroyConnection();
}

}
Loading