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
2,985 changes: 2,985 additions & 0 deletions modulo7/cookenu/package-lock.json

Large diffs are not rendered by default.

Binary file added modulo7/testes-backend/.DS_Store
Binary file not shown.
4 changes: 4 additions & 0 deletions modulo7/testes-backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
package-lock.json
build
.env
21 changes: 21 additions & 0 deletions modulo7/testes-backend/.rest
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### CADASTRO

POST http://localhost:3003/users/signup
Content-Type: application/json

{
"name": "Alice",
"email": "alice@lbn.com",
"password": "123456",
"role":"ADMIN"
}

### LOGIN

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

{
"email": "alice@lbn.com",
"password": "123456"
}
8 changes: 8 additions & 0 deletions modulo7/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"],
};
34 changes: 34 additions & 0 deletions modulo7/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": "jest --watchAll",
"start": "tsc && node --inspect ./build/src/index.js",
"dev": " ts-node-dev ./src/index.ts"
},
"author": "Labenu",
"license": "ISC",
"dependencies": {
"@types/knex": "^0.16.1",
"bcryptjs": "^2.4.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"knex": "^2.3.0",
"mysql": "^2.18.1",
"uuid": "^8.3.2"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/express": "^4.17.13",
"@types/jest": "^28.1.4",
"@types/jsonwebtoken": "^8.5.9",
"@types/uuid": "^7.0.3",
"jest": "^28.1.2",
"ts-jest": "^28.0.5",
"ts-node-dev": "^2.0.0",
"typescript": "^4.7.1"
}
}
Binary file added modulo7/testes-backend/src/.DS_Store
Binary file not shown.
18 changes: 18 additions & 0 deletions modulo7/testes-backend/src/business/Ports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { AuthenticationData } from "../services/tokenGenerator";

export interface IHashGenerator {
hash(s: string): Promise<any>
compareHash(s: string, hash: string): Promise<boolean>
}

export interface IIDGenerator {
generate(): string
}

export interface ITokenGenerator {
generate(input: AuthenticationData): string
verify(token: string): AuthenticationData
}



90 changes: 90 additions & 0 deletions modulo7/testes-backend/src/business/UserBusiness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { CustomError } from "../errors/CustomError";
import { User, stringToUserRole } from "../model/User";
import { IHashGenerator, IIDGenerator, ITokenGenerator } from "./Ports";
import { UserRepository } from "./UserRepository";


export class UserBusiness {
constructor(
private userDatabase: UserRepository,
private hashGenerator: IHashGenerator,
private idGenerator: IIDGenerator,
private tokenGenerator: ITokenGenerator
){}

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 = this.idGenerator.generate();

const cypherPassword = await this.hashGenerator.hash(password);

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

const accessToken = this.tokenGenerator.generate({
id,
role,
});
return { accessToken };
} catch (error:any) {
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 this.userDatabase.getUserByEmail(email);

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

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

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

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

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

8 changes: 8 additions & 0 deletions modulo7/testes-backend/src/business/UserRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { User } from "../model/User";

export interface UserRepository {
createUser(user: User): Promise<void>;
getUserByEmail(email: string): Promise<User | undefined>;
getUserById(id: string): Promise<User | undefined>;
getAllUsers(): Promise<User[]>;
}
37 changes: 37 additions & 0 deletions modulo7/testes-backend/src/controller/UserController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Request, Response } from "express";
import { UserBusiness } from "../business/UserBusiness";


export class UserController {
constructor(
private userBusiness: UserBusiness
){}

public async signup(req: Request, res: Response) {
try {
const { name, role, email, password } = req.body
const result = await this.userBusiness.signup(
name,
email,
password,
role
);
res.status(200).send(result);
} catch (error:any) {
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 this.userBusiness.login(email, password);
res.status(200).send(result);
} catch (error:any) {
const { statusCode, message } = error
res.status(statusCode || 400).send({ message });
}
}
}

23 changes: 23 additions & 0 deletions modulo7/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({
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 modulo7/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";
import { UserRepository } from "../business/UserRepository";

export class UserDatabase extends BaseDataBase implements UserRepository {

protected tableName: string = "INSIRA AQUI O NOME DA SUA TABELA DE USUÁRIOS";

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:any) {
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:any) {
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:any) {
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:any) {
throw new Error(error.sqlMessage || error.message)
}
}
}

export default new UserDatabase()
8 changes: 8 additions & 0 deletions modulo7/testes-backend/src/errors/CustomError.ts
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 modulo7/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.`);
}
});
Loading