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 semana20/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"],
};
1,975 changes: 1,975 additions & 0 deletions semana20/projeto-LAMA/package-lock.json

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions semana20/projeto-LAMA/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "lama-template",
"version": "1.0.0",
"description": "Template para o projeto LAMA",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "ts-node ./src/index.ts"
},
"keywords": [
"api",
"labook"
],
"author": "João Alves",
"license": "ISC",
"dependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/express": "^4.17.7",
"@types/jest": "^25.2.3",
"@types/jsonwebtoken": "^8.5.0",
"@types/knex": "^0.16.1",
"@types/uuid": "^8.0.0",
"bcryptjs": "^2.4.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"jest": "^26.0.1",
"knex": "^0.21.2",
"moment": "^2.27.0",
"mysql": "^2.18.1",
"ts-jest": "^26.1.0",
"ts-node": "^8.10.2",
"typescript": "^3.9.6",
"uuid": "^8.2.0"
}
}
43 changes: 43 additions & 0 deletions semana20/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;
}
}
50 changes: 50 additions & 0 deletions semana20/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) {
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) {
res.status(400).send({ error: error.message });
}

await BaseDatabase.destroyConnection();
}

}
32 changes: 32 additions & 0 deletions semana20/projeto-LAMA/src/data/BaseDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import knex from "knex";
import Knex from "knex";


export abstract class BaseDatabase {

private static connection: Knex | null = null;

protected getConnection(): Knex{
if(!BaseDatabase.connection){
BaseDatabase.connection = knex({
client: "mysql",
connection: {
host: process.env.DB_HOST,
port: 3306,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE_NAME,
},
});
}

return BaseDatabase.connection;
}

public static async destroyConnection(): Promise<void>{
if(BaseDatabase.connection){
await BaseDatabase.connection.destroy();
BaseDatabase.connection = null;
}
}
}
39 changes: 39 additions & 0 deletions semana20/projeto-LAMA/src/data/UserDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { BaseDatabase } from "./BaseDatabase";
import { User } from "../model/User";

export class UserDatabase extends BaseDatabase {

private static TABLE_NAME = "";

public async createUser(
id: string,
email: string,
name: string,
password: string,
role: string
): Promise<void> {
try {
await this.getConnection()
.insert({
id,
email,
name,
password,
role
})
.into(UserDatabase.TABLE_NAME);
} catch (error) {
throw new Error(error.sqlMessage || error.message);
}
}

public async getUserByEmail(email: string): Promise<User> {
const result = await this.getConnection()
.select("*")
.from(UserDatabase.TABLE_NAME)
.where({ email });

return User.toUserModel(result[0]);
}

}
6 changes: 6 additions & 0 deletions semana20/projeto-LAMA/src/error/BaseError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export abstract class BaseError extends Error {
constructor(message: string, public code: number) {
super(message);
}
}

19 changes: 19 additions & 0 deletions semana20/projeto-LAMA/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import dotenv from "dotenv";
import {AddressInfo} from "net";
import express from "express";
import { userRouter } from "./routes/userRouter";
dotenv.config();
const app = express();

app.use(express.json());

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

const server = app.listen(3000, () => {
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.`);
}
});
83 changes: 83 additions & 0 deletions semana20/projeto-LAMA/src/model/User.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
export class User{
constructor(
private id: string,
private name: string,
private email: string,
private password: string,
private role: UserRole
){}

getId(){
return this.id;
}

getName(){
return this.name
}

getEmail(){
return this.email;
}

getPassword(){
return this.password;
}

getRole(){
return this.role;
}

setId(id: string){
this.id = id;
}

setName(name: string){
this.name = name;
}

setEmail(email: string){
this.email = email;
}

setPassword(password: string){
this.password = password;
}

setRole(role: UserRole){
this.role = role;
}

static stringToUserRole(input: string): UserRole{
switch (input) {
case "NORMAL":
return UserRole.NORMAL;
case "ADMIN":
return UserRole.ADMIN;
default:
throw new Error("Invalid user role");
}
}

static toUserModel(user: any): User {
return new User(user.id, user.name, user.email, user.password, User.stringToUserRole(user.role));
}


}

export interface UserInputDTO{
email: string;
password: string;
name: string;
role: string;
}

export interface LoginInputDTO{
email: string;
password: string;
}

export enum UserRole{
NORMAL = "NORMAL",
ADMIN = "ADMIN"
}
10 changes: 10 additions & 0 deletions semana20/projeto-LAMA/src/routes/userRouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import express from "express";
import { UserController } from "../controller/UserController";


export const userRouter = express.Router();

const userController = new UserController();

userRouter.post("/signup", userController.signup);
userRouter.post("/login", userController.login);
32 changes: 32 additions & 0 deletions semana20/projeto-LAMA/src/services/Authenticator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as jwt from "jsonwebtoken";

export class Authenticator {
public generateToken(input: AuthenticationData,
expiresIn: string = process.env.ACCESS_TOKEN_EXPIRES_IN!): string {
const token = jwt.sign(
{
id: input.id,
role: input.role
},
process.env.JWT_KEY as string,
{
expiresIn,
}
);
return token;
}

public getData(token: string): AuthenticationData {
const payload = jwt.verify(token, process.env.JWT_KEY as string) as any;
const result = {
id: payload.id,
role: payload.role
};
return result;
}
}

interface AuthenticationData {
id: string;
role?: string;
}
17 changes: 17 additions & 0 deletions semana20/projeto-LAMA/src/services/HashManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as bcrypt from "bcryptjs";


export class HashManager {

public async hash(text: string): Promise<string> {
const rounds = 12;
const salt = await bcrypt.genSalt(rounds);
const result = await bcrypt.hash(text, salt);
return result;
}

public async compare(text: string, hash: string): Promise<boolean>{
return await bcrypt.compare(text, hash);
}

}
Loading