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
3 changes: 3 additions & 0 deletions modulo5/arquitetura-camadas/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules
package-lock.json
.env
35 changes: 35 additions & 0 deletions modulo5/arquitetura-camadas/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "arquitetura-camadas",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "tsc && node --inspect ./build/index.js",
"dev": "ts-node-dev --transpile-only --ignore-watch node_modules ./src/index.ts",
"test": "ts-node-dev ./src/services/authenticator.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"dotenv": "^8.6.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"knex": "^0.21.5",
"mysql": "^2.18.1",
"ts-node-dev": "^2.0.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/cors": "^2.8.8",
"@types/express": "^4.17.8",
"@types/jsonwebtoken": "^8.5.9",
"@types/knex": "^0.16.1",
"@types/node": "^14.11.2",
"@types/uuid": "^8.3.4",
"typescript": "^4.0.3"
}
}
15 changes: 15 additions & 0 deletions modulo5/arquitetura-camadas/request.rest
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
POST http://localhost:3003/user/signup Content-Type: application/json

{
"name": "Lucas", "email": "lucas@gmailSDASDASDASDASDSADASDASD.com", "password": "abc1254"
}

### POST http://localhost:3003/user/login Content-Type: application/json

{
"email": "lucas@gmailSDASDASDASDASDSADASDASD.com", "password": "abc1254"
}

### GET http://localhost:3003/user Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImQ2YmRhOGUwLTAxZmEtNDUyZS1hYjg2LTFmYjA4OTU2OWFlNiIsInJvbGUiOiJOT1JNQUwiLCJpYXQiOjE2NjM2MDkwMzYsImV4cCI6MTY2MzY1MjIzNn0.TZpUcqk1JvZf90oGEJi8vgvmSavpU532ybfPEVqCDbw

### DELETE http://localhost:3003/user/d6bda8e0-01fa-452e-ab86-1fb089569ae6 Authorization:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImI3NzJmZGY0LWM5ZmItNDJjMi1hNGJmLTVhZThiODViNTE5YiIsInJvbGUiOiJBRE1JTiIsImlhdCI6MTY2MzYxMDg0MCwiZXhwIjoxNjYzNjU0MDQwfQ.UnW6aalc52xq54ToXwT1uV-S1QIxAhaF84dfDda5xIs
118 changes: 118 additions & 0 deletions modulo5/arquitetura-camadas/src/Controller/UserController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { Request, Response } from "express";
import UserBusiness from "../business/UserBusiness";
import { InvalidError } from "../error/invalidError";
import { MissingFields } from "../error/MissingFields";
import { CreateNewUser, User } from "../model/User";


class UserController {

public signup = async (req: Request, res: Response) => {

try {
const {name, email, password} = req.body

if(!name || !email || !password) {
throw new MissingFields()
}

const newUser: CreateNewUser = {
name: name,
email: email,
password: password
}

const userBusiness = new UserBusiness()
const user = await userBusiness.signup(newUser)

res.status(201).send(user)

} catch (error) {
if(error instanceof Error) {
return res.status(400).send({message: error.message})
}

res.status(500).send({message: "Erro inesperado"})
}

}

public login = async (req: Request, res: Response): Promise<void> => {
try {
const {email, password} = req.body

if(!email || !password) {
throw new MissingFields()
}

const userBusiness = new UserBusiness();

const loginUser = await userBusiness.login(email, password)

res.status(200).send(loginUser)

} catch (error: any) {
res.status(error.statusCode || 500)
.send({ message: error.message || "Erro inesperado" })

}
}

public getAllUsers = async (req: Request, res: Response) => {
try {

const token = req.headers.authorization as string

if(!token) {
throw new InvalidError("Token não foi enviado")
}

const userBusiness = new UserBusiness()

const allUsers = await userBusiness.selectAllUsers(token)

res.status(200).send(allUsers)

} catch (error) {
if(error instanceof Error) {
return res.status(400).send({message: error.message})
}

res.status(500).send({message: "Erro inesperado"})

}
}

public deleteUser = async (req: Request, res: Response): Promise<void> => {
try {
const token = req.headers.authorization as string
const id = req.params.id

if(!token) {
throw new InvalidError("Token não foi enviado")
}

if(!id) {
throw new InvalidError("Seu Id não foi informado")
}

const userBusiness = new UserBusiness()

const deleteUser = await userBusiness.deleteUser(token, id)

res.status(200).send(deleteUser)

} catch (error: any) {
res.status(error.statusCode || 500)
.send({ message: error.message || "Erro inesperado" })
}


}
}





export default UserController
19 changes: 19 additions & 0 deletions modulo5/arquitetura-camadas/src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import express from "express";
import cors from "cors";
import { AddressInfo } from "net";

const app = express();

app.use(express.json());
app.use(cors());

const server = app.listen(process.env.PORT || 3003, () => {
if (server) {
const address = server.address() as AddressInfo;
console.log(`Server is running in http://localhost:${address.port}`);
} else {
console.error(`Failure upon starting server.`);
}
});

export default app
173 changes: 173 additions & 0 deletions modulo5/arquitetura-camadas/src/business/UserBusiness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { type } from "os";
import UserDataBase from "../dataBase/UserDataBase";
import { InsufficientAuthorization } from "../error/InsufficientAuthorization";
import { InvalidCredentiais } from "../error/InvalidCredentiais";
import { InvalidError } from "../error/invalidError";
import { CreateNewUser, User, UserDB, USER_ROLES } from "../model/User";
import Authenticator, { TokenPayload } from "../service/Authenticator";
import GenerateId from "../service/GenerateId";
import { HashManager } from "../service/HashManager";



class UserBusiness {
public signup = async (user: CreateNewUser) => {

const {name, email, password} = user


if(!name || typeof name !== "string" || name.length < 3) {
throw new InvalidError("Parâmetro 'name'' inválido")
}

if(!email || typeof email !== "string") {
throw new InvalidError("Parâmetro 'email' inválido")
}

if(email.indexOf("@") == -1) {
throw new InvalidError("Seu email deve possuir um @ em sua composição")
}

if(!password || typeof password !== "string" || password.length < 6) {
throw new InvalidError("Parâmetro 'password' inválido")
}

const UserData = new UserDataBase()

const userDB = await UserData.getUserByEmail(email)

if(userDB) {
throw new InvalidError("Email já cadastrado")
}

const idGenerator = new GenerateId()
const id = idGenerator.createId()

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

const newUser = new User(
id,
name,
email,
hashPassword
)

await UserData.createUser(newUser)

const payload: TokenPayload = {
id: newUser.getId(),
role: newUser.getRole()
}

const authenticator = new Authenticator()
const token = authenticator.generateToken(payload)

const response = {
message: "Seu usuário foi criado",
token
}

return response

}

public login = async (email: string, password: string) => {

if(email.indexOf("@") === -1 || typeof email !== "string"){
throw new InvalidError("O Seu Email está em formato inválido")
}

if(password.length < 6) {
throw new InvalidError("Sua senha deve possuir mais de 6 caracteres")
}

const userData = new UserDataBase()

const userDB = await userData.getUserByEmail(email)

if(!userDB) {
throw new InvalidCredentiais()
}

const hashManager = new HashManager()

const correctPassword = await hashManager.compare(password, userDB.password)

if(!correctPassword) {
throw new InvalidCredentiais()
}

const payload: TokenPayload = {
id: userDB.id,
role: userDB.role
}

const token = new Authenticator().generateToken(payload)

const response = {
acess_Token: token
}


return response


}

public selectAllUsers = async (token: string) => {

const userData = new UserDataBase()

const authenticator = new Authenticator()
const payload = authenticator.verifyToken(token)

if(!payload) {
throw new InvalidCredentiais()
}

const users = await userData.getAllUsers()

if(!users) {
throw new InvalidError("Não existe usuários")
}



return users

}

public deleteUser = async (token: string, id: string) => {
const authenticator = new Authenticator()
const payload = authenticator.verifyToken(token)

if(payload.role !== USER_ROLES.ADMIN) {
throw new InsufficientAuthorization();

}

const userData = new UserDataBase()
const userDB = await userData.getUserById(id)

if(!userDB) {
throw new InvalidError("O Perfil não foi encontrado")
}

if(userDB.id === payload.id) {
throw new InvalidError("Você não pode apagar seu perfil estando logado nele")
}

await userData.removeAccount(id)

const response = {
message: "A Conta foi apagada com sucesso"
}

return response
}

}


export default UserBusiness
Loading