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
Binary file not shown.
6 changes: 6 additions & 0 deletions Semana19/Aula4/template-testes-backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/
build/
.vscode/

.env
.rest
8 changes: 8 additions & 0 deletions Semana19/Aula4/template-testes-backend/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"],
};
7,571 changes: 7,571 additions & 0 deletions Semana19/Aula4/template-testes-backend/package-lock.json

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions Semana19/Aula4/template-testes-backend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "testes-no-backend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "clear && echo \"Running tests...\" && jest",
"start": "tsc && node --inspect ./build/src/index.js",
"dev": " ts-node-dev ./src/index.ts"
},
"author": "Labenu",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"knex": "^0.21.1",
"mysql": "^2.18.1",
"uuid": "^8.0.0"
},
"devDependencies": {
"jest": "^26.0.1",
"ts-jest": "^26.1.0",
"typescript": "^3.9.2",
"ts-node-dev": "^1.0.0-pre.44",
"@types/bcryptjs": "^2.4.2",
"@types/express": "^4.17.6",
"@types/jest": "^25.2.3",
"@types/jsonwebtoken": "^8.5.0",
"@types/knex": "^0.16.1",
"@types/uuid": "^7.0.3"
}
}
Binary file not shown.
108 changes: 108 additions & 0 deletions Semana19/Aula4/template-testes-backend/src/business/UserBusiness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { CustomError } from "../errors/CustomError";
import { User, stringToUserRole } from "../model/User";
import userDatabase from "../data/UserDatabase";
import hashGenerator from "../services/hashGenerator";
import idGenerator from "../services/idGenerator";
import tokenGenerator from "../services/tokenGenerator";
import UserDatabase from "../data/UserDatabase";

export class UserBusiness {

public async signup(
name: string,
email: string,
password: string,
role: string
) {
try {
if (!name || !email || !password || !role) {
throw new CustomError(422, "Missing input");
}

if (email.indexOf("@") === -1) {
throw new CustomError(422, "Invalid email");
}

if (password.length < 6) {
throw new CustomError(422, "Invalid password");
}

const id = idGenerator.generate();

const cypherPassword = await hashGenerator.hash(password);

await userDatabase.createUser(
new User(id, name, email, cypherPassword, stringToUserRole(role))
);

const accessToken = tokenGenerator.generate({
id,
role,
});
return { accessToken };
} catch (error) {
if (error.message.includes("key 'email'")) {
throw new CustomError(409, "Email already in use")
}

throw new CustomError(error.statusCode, error.message)
}

}

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

try {
if (!email || !password) {
throw new CustomError(422, "Missing input");
}

const user = await userDatabase.getUserByEmail(email);

if (!user) {
throw new CustomError(401, "Invalid credentials");
}

const isPasswordCorrect = await hashGenerator.compareHash(
password,
user.getPassword()
);

if (!isPasswordCorrect) {
throw new CustomError(401, "Invalid credentials");
}

const accessToken = tokenGenerator.generate({
id: user.getId(),
role: user.getRole(),
});

return { accessToken };
} catch (error) {
throw new CustomError(error.statusCode, error.message)
}
}

public async getUserById(id: string) {
try {
const user = await UserDatabase.getUserById(id);

if (!user) {
throw new CustomError(402, "Id not a String");
}

return {
id: user.getId(),
name: user.getName(),
email: user.getEmail(),
role: user.getRole(),
};

} catch (error) {
throw new CustomError(error.statusCode, error.message)
}

}
}

export default new UserBusiness()
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Request, Response } from "express";
import userBusiness from "../business/UserBusiness";
import UserDatabase from "../data/UserDatabase";

export class UserController {

public async signup(req: Request, res: Response) {
try {
const { name, role, email, password } = req.body
const result = await userBusiness.signup(
name,
email,
password,
role
);
res.status(200).send(result);
} catch (error) {
const { statusCode, message } = error
res.status(statusCode || 400).send({ message });
}
}

public async login(req: Request, res: Response) {
try {
const { email, password } = req.body
const result = await userBusiness.login(email, password);
res.status(200).send(result);
} catch (error) {
const { statusCode, message } = error
res.status(statusCode || 400).send({ message });
}
}

public async profile(req: Request, res: Response) {
try {

const id = req.params.id
const result = await userBusiness.getUserById(id)
console.log(result)
res.status(200).send(result)
} catch (error) {
const { statusCode, message } = error
res.status(statusCode || 400).send({ message });
}
}
}

export default new UserController()
23 changes: 23 additions & 0 deletions Semana19/Aula4/template-testes-backend/src/data/BaseDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import dotenv from "dotenv";
import knex from "knex";

dotenv.config();

export default class BaseDataBase {

protected static connection: knex = knex({
client: "mysql",
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_SCHEMA,
port: 3306,
multipleStatements: true
},
});

public static async destroyConnection(): Promise<void> {
await BaseDataBase.connection.destroy();
}
}
74 changes: 74 additions & 0 deletions Semana19/Aula4/template-testes-backend/src/data/UserDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import BaseDataBase from "./BaseDatabase";
import { User } from "../model/User";

export class UserDatabase extends BaseDataBase {

protected tableName: string = "UserSemana19";

private toModel(dbModel?: any): User | undefined {
return (
dbModel &&
new User(
dbModel.id,
dbModel.name,
dbModel.email,
dbModel.password,
dbModel.role
)
);
}

public async createUser(user: User): Promise<void> {
try {
await BaseDataBase.connection.raw(`
INSERT INTO ${this.tableName} (id, name, email, password, role)
VALUES (
'${user.getId()}',
'${user.getName()}',
'${user.getEmail()}',
'${user.getPassword()}',
'${user.getRole()}'
)`
);
} catch (error) {
throw new Error(error.sqlMessage || error.message)
}
}

public async getUserByEmail(email: string): Promise<User | undefined> {
try {
const result = await BaseDataBase.connection.raw(`
SELECT * from ${this.tableName} WHERE email = '${email}'
`);
return this.toModel(result[0][0]);
} catch (error) {
throw new Error(error.sqlMessage || error.message)
}
}

public async getUserById(id: string): Promise<User | undefined> {
try {
const result = await BaseDataBase.connection.raw(`
SELECT * from ${this.tableName} WHERE id = '${id}'
`);
return this.toModel(result[0][0]);
} catch (error) {
throw new Error(error.sqlMessage || error.message)
}
}

public async getAllUsers(): Promise<User[]> {
try {
const result = await BaseDataBase.connection.raw(`
SELECT * from ${this.tableName}
`);
return result[0].map((res: any) => {
return this.toModel(res);
});
} catch (error) {
throw new Error(error.sqlMessage || error.message)
}
}
}

export default new UserDatabase()
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class CustomError extends Error {
constructor(
public statusCode: number,
message: string
) {
super(message);
}
}
18 changes: 18 additions & 0 deletions Semana19/Aula4/template-testes-backend/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import express from "express";
import {AddressInfo} from "net";
import { userRouter } from "./router/UserRouter";

const app = express();

app.use(express.json());

app.use("/users", userRouter);

const server = app.listen(3003, () => {
if (server) {
const address = server.address() as AddressInfo;
console.log(`Servidor rodando em http://localhost:${address.port}`);
} else {
console.error(`Falha ao rodar o servidor.`);
}
});
47 changes: 47 additions & 0 deletions Semana19/Aula4/template-testes-backend/src/model/User.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { CustomError } from "../errors/CustomError";

export class User {
constructor(
private id: string,
private name: string,
private email: string,
private password: string,
private role: USER_ROLES
) { }

public getId(): string {
return this.id;
}

public getName(): string {
return this.name;
}

public getEmail(): string {
return this.email;
}

public getPassword(): string {
return this.password;
}

public getRole(): USER_ROLES {
return this.role;
}
}

export const stringToUserRole = (input: string): USER_ROLES => {
switch (input) {
case "NORMAL":
return USER_ROLES.NORMAL;
case "ADMIN":
return USER_ROLES.ADMIN;
default:
throw new CustomError(422, "Invalid user role");
}
};

export enum USER_ROLES {
NORMAL = "NORMAL",
ADMIN = "ADMIN",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import express from "express";
import userController from "../controller/UserController";

export const userRouter = express.Router();

userRouter.post("/signup", userController.signup);
userRouter.post("/login", userController.login);
userRouter.get("/profile/:id", userController.profile);
Loading