diff --git "a/Backend/Semana4/aula1/Aula 50 - Introduc\314\247a\314\203o a Autenticac\314\247a\314\203o.pdf" "b/Backend/Semana4/aula1/Aula 50 - Introduc\314\247a\314\203o a Autenticac\314\247a\314\203o.pdf" new file mode 100644 index 0000000..70ee5df Binary files /dev/null and "b/Backend/Semana4/aula1/Aula 50 - Introduc\314\247a\314\203o a Autenticac\314\247a\314\203o.pdf" differ diff --git a/Backend/Semana4/aula1/Intro_autenticacao/.gitignore b/Backend/Semana4/aula1/Intro_autenticacao/.gitignore new file mode 100644 index 0000000..68c82c2 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/.gitignore @@ -0,0 +1,4 @@ +node_modules +packege-lock.json +build +.env \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/README.md b/Backend/Semana4/aula1/Intro_autenticacao/README.md new file mode 100644 index 0000000..c6842b0 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/README.md @@ -0,0 +1,100 @@ +# To Do List + +## ESTRUTURA DE DADOS + +* ## Usuários + * id + * name + * nickname + * email + +* ## Tarefas + * id + * title + * description + * deadline + * status: `"to_do" || "doing" || "done"` + * author + * assignees + +--- + +## CRIAÇÃO DE TABELAS - MySql + +```sql +CREATE TABLE to_do_list_users ( + id VARCHAR(64) PRIMARY KEY, + name VARCHAR(64) NOT NULL, + nickname VARCHAR(64) NOT NULL, + email VARCHAR(64) NOT NULL +); +``` +```sql +CREATE TABLE to_do_list_tasks ( + id VARCHAR(64) PRIMARY KEY, + title VARCHAR(64) NOT NULL, + description VARCHAR(1024) DEFAULT "No description provided", + deadline DATE, + status ENUM("TO_DO", "DOING", "DONE") DEFAULT "TO_DO", + author_id VARCHAR(64), + FOREIGN KEY (author_id) REFERENCES to_do_list_users(id) +); +``` +```sql +CREATE TABLE to_do_list_assignees ( + task_id VARCHAR(64), + assignee_id VARCHAR(64), + PRIMARY KEY (task_id, assignee_id), + FOREIGN KEY (task_id) REFERENCES to_do_list_tasks(id), + FOREIGN KEY (assignee_id) REFERENCES to_do_list_users(id) +); +``` +--- + +## ENDPOINTS + +* ## Criar usuário + * Método: PUT + * Path: `/user` + * Body: + * name (obrigatório) + * nickname (obrigatório) + * email (obrigatório) + +* ## Pegar usuário pelo id + * Método: GET + * Path: `/user/:id` + * Body de Resposta: (retornar um erro se não encontrar) + * id + * nickname + + +* ## Editar usuário** + * Método: POST + * Path: `/user/edit/:id` + * Body: + * name (opcional; não pode ser vazio) + * nickname (opcional; não pode ser vazio) + * email (opcional; não pode ser vazio) + + +* ## Criar tarefa + * Método: PUT + * Path: `/task` + * Body: + * title (obrigatório) + * description (obrigatório) + * deadline (obrigatório; formato `YYYY-MM-DD`) + * authorId + +* ## Pegar tarefa pelo id + * Método: GET + * Path: `/task/:id` + * Body de Resposta: (retornar um erro se não encontrar) + * id + * title + * description + * deadline (formato `YYYY-MM-DD`) + * status + * authorId + * authorNickname \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/package.json b/Backend/Semana4/aula1/Intro_autenticacao/package.json new file mode 100644 index 0000000..7dad6bd --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/package.json @@ -0,0 +1,29 @@ +{ + "name": "to-do-list", + "version": "1.0.0", + "description": "## ESTRUTURA DE DADOS", + "main": "index.js", + "scripts": { + "start": "tsc && node --inspect ./build/index.js", + "dev": "ts-node-dev ./src/index.ts", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "cors": "^2.8.5", + "dotenv": "^8.2.0", + "express": "^4.17.1", + "knex": "^0.21.5", + "mysql": "^2.18.1" + }, + "devDependencies": { + "@types/cors": "^2.8.8", + "@types/express": "^4.17.8", + "@types/knex": "^0.16.1", + "@types/node": "^14.11.2", + "ts-node-dev": "^1.0.0-pre.63", + "typescript": "^4.0.3" + } +} diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/data/insertTask.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/data/insertTask.ts new file mode 100644 index 0000000..50464df --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/data/insertTask.ts @@ -0,0 +1,18 @@ +import { connection } from ".."; + +export default async function insertTask( + id: string, + title: string, + description: string, + deadline: string, + authorId: string +) { + await connection('to_do_list_tasks') + .insert({ + id, + title, + description, + deadline, + author_id: authorId + }) +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/data/insertUser.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/data/insertUser.ts new file mode 100644 index 0000000..757c156 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/data/insertUser.ts @@ -0,0 +1,15 @@ +import { connection } from "../index"; + +export default async function insertUser( + id: string, + name: string, + nickname: string, + email: string +) { + await connection.insert({ + id, + name, + nickname, + email + }).into('to_do_list_users') +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/data/selectTaskById.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/data/selectTaskById.ts new file mode 100644 index 0000000..eb0d3df --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/data/selectTaskById.ts @@ -0,0 +1,14 @@ +import { connection } from ".."; + +export default async function selectTaskById( + id: string +): Promise { + const result = await connection.raw(` + SELECT tasks.*, nickname FROM to_do_list_tasks AS tasks + JOIN to_do_list_users AS users + ON author_id = users.id + WHERE tasks.id = '${id}'; + `) + + return result[0][0] +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/data/selectUserById.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/data/selectUserById.ts new file mode 100644 index 0000000..f1e4cb1 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/data/selectUserById.ts @@ -0,0 +1,11 @@ +import { connection } from ".."; + +export default async function selectUserById( + id: string +) { + const result = await connection('to_do_list_users') + .select('*') + .where({ id }) + + return result[0] +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/data/updateUser.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/data/updateUser.ts new file mode 100644 index 0000000..8ed0c1b --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/data/updateUser.ts @@ -0,0 +1,18 @@ +import { connection } from ".."; + +export default async function updateUser( + id: string, + name?: string, + nickname?: string, + email?: string +) { + + await connection("to_do_list_users") + .update({ + name, nickname, email + }) + .where({ + id + }) + +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/createTask.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/createTask.ts new file mode 100644 index 0000000..d26a685 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/createTask.ts @@ -0,0 +1,42 @@ +import { Request, Response } from "express"; +import insertTask from "../data/insertTask"; + +export default async function createTask( + req: Request, + res: Response +) { + try { + if ( + !req.body.title || + !req.body.description || + !req.body.deadline || + !req.body.authorId + ) { + throw new Error('"title", "description", "deadline" e "authorId" são obrigatórios') + } + + const id: string = Date.now() + Math.random().toString() + + await insertTask( + id, + req.body.title, + req.body.description, + req.body.deadline, + req.body.authorId, + ) + + res.status(400).send({ + message: "Tarefa criada com sucesso!", + id + }) + + } catch (error) { + let message = error.sqlMessage || error.message + + if (message.includes("date")) { + message = "'deadline' deve ser uma data válida, no formato aaaa-mm-dd" + } + + res.status(400).send({ message }) + } +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/createUser.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/createUser.ts new file mode 100644 index 0000000..6da03d7 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/createUser.ts @@ -0,0 +1,36 @@ +import { Request, Response } from "express"; +import insertUser from "../data/insertUser"; + +export default async function createUser( + req: Request, + res: Response +) { + try { + + if ( + !req.body.name || + !req.body.nickname || + !req.body.email + ) { + throw new Error('Preencha os campos "name","nickname" e "email"') + } + + const id: string = Date.now() + Math.random().toString() + + await insertUser( + id, + req.body.name, + req.body.nickname, + req.body.email + ) + + res + .status(200) + .send('Usuário criado com sucesso!') + + } catch (error) { + res.status(400).send({ + message: error.message || error.sqlMessage + }) + } +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/editUser.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/editUser.ts new file mode 100644 index 0000000..3f9f2bd --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/editUser.ts @@ -0,0 +1,38 @@ +import { Request, Response } from "express"; +import updateUser from "../data/updateUser"; + +export default async function editUser( + req: Request, + res: Response +) { + try { + if ( + req.body.name === '' || + req.body.nickname === '' || + req.body.email === '' + ) { + throw new Error("Nenhum dos campos pode estar em branco") + } + + if (!req.body.name && !req.body.nickname && !req.body.email) { + throw new Error("Escolha ao menos um valor para alterar") + } + + await updateUser( + req.params.id, + req.body.name, + req.body.nickname, + req.body.email + ) + + + res.status(200).send({ + message: "Usuário atualizado!" + }) + + } catch (error) { + res.status(400).send({ + message: error.message || error.sqlMessage + }) + } +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/getTaskById.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/getTaskById.ts new file mode 100644 index 0000000..7587607 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/getTaskById.ts @@ -0,0 +1,30 @@ +import { Request, Response } from "express"; +import selectTaskById from "../data/selectTaskById"; + +export default async function getTaskById( + req: Request, + res: Response +) { + try { + const result = await selectTaskById(req.params.id) + + if (!result) { + throw new Error("Tarefa não encontrada") + } + + res.status(200).send({ + id: result.id, + title: result.title, + description: result.description, + deadline: result.deadline, + status: result.status, + authorId: result.author_id, + authorNickname: result.nickname + }) + + } catch (error) { + res.status(400).send({ + message: error.message || error.sqlMessage + }) + } +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/getUserById.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/getUserById.ts new file mode 100644 index 0000000..778cf1c --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/endpoints/getUserById.ts @@ -0,0 +1,25 @@ +import { Request, Response } from "express"; +import selectUserById from "../data/selectUserById"; + +export default async function getUserById( + req: Request, + res: Response +) { + try { + const user = await selectUserById(req.params.id) + + if (!user) { + throw new Error("Usuário não encontrado") + } + + res.status(200).send({ + id: user.id, + nickname: user.nickname + }) + + } catch (error) { + res.status(400).send({ + message: error.message || error.sqlMessage + }) + } +} \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/src/index.ts b/Backend/Semana4/aula1/Intro_autenticacao/src/index.ts new file mode 100644 index 0000000..dad5b6f --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/src/index.ts @@ -0,0 +1,38 @@ +import express from 'express' +import knex from 'knex' +import cors from 'cors' +import dotenv from 'dotenv' +import createUser from './endpoints/createUser' +import getUserById from './endpoints/getUserById' +import editUser from './endpoints/editUser' +import createTask from './endpoints/createTask' +import getTaskById from './endpoints/getTaskById' + +dotenv.config() + +export const connection = knex({ + client: 'mysql', + connection: { + host: process.env.DB_HOST, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + port: 3306 + } +}) + + +const app = express() +app.use(express.json()) +app.use(cors()) + +app.put('/user', createUser) +app.get('/user/:id', getUserById) +app.post('/user/:id/edit', editUser) + +app.put('/task', createTask) +app.get('/task/:id', getTaskById) + +app.listen(3003, ()=>{ + console.log('Servidor rodando na porta 3003') +}) \ No newline at end of file diff --git a/Backend/Semana4/aula1/Intro_autenticacao/tables.sql b/Backend/Semana4/aula1/Intro_autenticacao/tables.sql new file mode 100644 index 0000000..b0116b4 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/tables.sql @@ -0,0 +1,31 @@ +CREATE TABLE `to_do_list_users` ( + `id` varchar(64) NOT NULL, + `name` varchar(64) NOT NULL, + `nickname` varchar(64) NOT NULL, + `email` varchar(64) NOT NULL, + `password` varchar(255) NOT NULL, + `role` enum('NORMAL','ADMIN') DEFAULT 'NORMAL', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + + +CREATE TABLE `to_do_list_tasks` ( + `id` varchar(64) NOT NULL, + `title` varchar(64) NOT NULL, + `description` varchar(1024) DEFAULT 'No description provided', + `deadline` date DEFAULT NULL, + `status` enum('TO_DO','DOING','DONE') DEFAULT 'TO_DO', + `author_id` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `author_id` (`author_id`), + CONSTRAINT `to_do_list_tasks_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `to_do_list_users` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +CREATE TABLE `to_do_list_assignees` ( + `task_id` varchar(64) NOT NULL, + `assignee_id` varchar(64) NOT NULL, + PRIMARY KEY (`task_id`,`assignee_id`), + KEY `assignee_id` (`assignee_id`), + CONSTRAINT `to_do_list_assignees_ibfk_1` FOREIGN KEY (`task_id`) REFERENCES `to_do_list_tasks` (`id`), + CONSTRAINT `to_do_list_assignees_ibfk_2` FOREIGN KEY (`assignee_id`) REFERENCES `to_do_list_users` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; diff --git a/Backend/Semana4/aula1/Intro_autenticacao/tsconfig.json b/Backend/Semana4/aula1/Intro_autenticacao/tsconfig.json new file mode 100644 index 0000000..1abdfc7 --- /dev/null +++ b/Backend/Semana4/aula1/Intro_autenticacao/tsconfig.json @@ -0,0 +1,69 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./build", /* Redirect output structure to the directory. */ + "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +} diff --git a/Backend/Semana4/aula1/__MACOSX/._.env b/Backend/Semana4/aula1/__MACOSX/._.env new file mode 100644 index 0000000..30ef2e2 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/._.env differ diff --git a/Backend/Semana4/aula1/__MACOSX/._.gitignore b/Backend/Semana4/aula1/__MACOSX/._.gitignore new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/._.gitignore differ diff --git a/Backend/Semana4/aula1/__MACOSX/._README.md b/Backend/Semana4/aula1/__MACOSX/._README.md new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/._README.md differ diff --git a/Backend/Semana4/aula1/__MACOSX/._package.json b/Backend/Semana4/aula1/__MACOSX/._package.json new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/._package.json differ diff --git a/Backend/Semana4/aula1/__MACOSX/._src b/Backend/Semana4/aula1/__MACOSX/._src new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/._src differ diff --git a/Backend/Semana4/aula1/__MACOSX/._tsconfig.json b/Backend/Semana4/aula1/__MACOSX/._tsconfig.json new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/._tsconfig.json differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/._data b/Backend/Semana4/aula1/__MACOSX/src/._data new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/._data differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/._endpoints b/Backend/Semana4/aula1/__MACOSX/src/._endpoints new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/._endpoints differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/._index.ts b/Backend/Semana4/aula1/__MACOSX/src/._index.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/._index.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/data/._insertTask.ts b/Backend/Semana4/aula1/__MACOSX/src/data/._insertTask.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/data/._insertTask.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/data/._insertUser.ts b/Backend/Semana4/aula1/__MACOSX/src/data/._insertUser.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/data/._insertUser.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/data/._selectTaskById.ts b/Backend/Semana4/aula1/__MACOSX/src/data/._selectTaskById.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/data/._selectTaskById.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/data/._selectUserById.ts b/Backend/Semana4/aula1/__MACOSX/src/data/._selectUserById.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/data/._selectUserById.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/data/._updateUser.ts b/Backend/Semana4/aula1/__MACOSX/src/data/._updateUser.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/data/._updateUser.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/endpoints/._createTask.ts b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._createTask.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._createTask.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/endpoints/._createUser.ts b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._createUser.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._createUser.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/endpoints/._editUser.ts b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._editUser.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._editUser.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/endpoints/._getTaskById.ts b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._getTaskById.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._getTaskById.ts differ diff --git a/Backend/Semana4/aula1/__MACOSX/src/endpoints/._getUserById.ts b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._getUserById.ts new file mode 100644 index 0000000..afe3525 Binary files /dev/null and b/Backend/Semana4/aula1/__MACOSX/src/endpoints/._getUserById.ts differ diff --git a/Backend/Semana4/aula1/exercicio-semana4-aula1/boilerplate_autenticacao.zip b/Backend/Semana4/aula1/exercicio-semana4-aula1/boilerplate_autenticacao.zip new file mode 100644 index 0000000..98e93c0 Binary files /dev/null and b/Backend/Semana4/aula1/exercicio-semana4-aula1/boilerplate_autenticacao.zip differ diff --git a/Backend/Semana4/aula1/template-intro-autenticacao.zip b/Backend/Semana4/aula1/template-intro-autenticacao.zip new file mode 100644 index 0000000..ffc709f Binary files /dev/null and b/Backend/Semana4/aula1/template-intro-autenticacao.zip differ diff --git a/Backend/Semana4/projeto_cookenu/.gitignore b/Backend/Semana4/projeto_cookenu/.gitignore new file mode 100644 index 0000000..8ece3ba --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/.gitignore @@ -0,0 +1,4 @@ +node_modules +package-lock.json +build +.env \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/package.json b/Backend/Semana4/projeto_cookenu/package.json new file mode 100644 index 0000000..e1e5c30 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/package.json @@ -0,0 +1,38 @@ +{ + "name": "projeto_cookenu", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "dev": "ts-node-dev ./src/index.ts", + "start": "tsc && node ./build/index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/cors": "^2.8.9", + "@types/express": "^4.17.11", + "ts-node-dev": "^1.1.1", + "typescript": "^4.1.3" + }, + "dependencies": { + "@types/axios": "^0.14.0", + "@types/bcryptjs": "^2.4.2", + "@types/jsonwebtoken": "^8.5.0", + "@types/knex": "^0.16.1", + "@types/nodemailer": "^6.4.0", + "@types/uuid": "^8.3.0", + "axios": "^0.21.1", + "bcryptjs": "^2.4.3", + "cors": "^2.8.5", + "dotenv": "^8.2.0", + "express": "^4.17.1", + "jsonwebtoken": "^8.5.1", + "knex": "^0.21.16", + "mysql": "^2.18.1", + "nodemailer": "^6.4.17", + "uuid": "^8.3.2" + } +} diff --git a/Backend/Semana4/projeto_cookenu/request.rest b/Backend/Semana4/projeto_cookenu/request.rest new file mode 100644 index 0000000..e69de29 diff --git a/Backend/Semana4/projeto_cookenu/src/data/getUserByEmail.ts b/Backend/Semana4/projeto_cookenu/src/data/getUserByEmail.ts new file mode 100644 index 0000000..9521f75 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/data/getUserByEmail.ts @@ -0,0 +1,9 @@ +import { connection } from '../index' +export async function getUserByEmail(email: string) { + const result = await + connection + .select("*") + .from("cookenu_users") + .where({ email }); + return result[0]; +}; \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/data/insertUser.ts b/Backend/Semana4/projeto_cookenu/src/data/insertUser.ts new file mode 100644 index 0000000..cff1046 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/data/insertUser.ts @@ -0,0 +1,14 @@ +import { connection } from "../index"; +export default async function insertUser( + id: string, + name: string, + email: string, + password: string, +) { + await connection.insert({ + id, + name, + email, + password + }).into('cookenu_users') +} \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/endpoints/login.ts b/Backend/Semana4/projeto_cookenu/src/endpoints/login.ts new file mode 100644 index 0000000..03c6612 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/endpoints/login.ts @@ -0,0 +1,33 @@ +import { Request, Response } from "express"; +import { getUserByEmail } from "../data/getUserByEmail"; +import { generateToken } from "../services/authenticator"; +import { compare } from "../services/hashManager"; +import { loginInput } from '../types/loginInput'; + + +export async function login(req: Request, res: Response) { + try { + const input: loginInput = { + email: req.body.email, + password: req.body.password + }; + if (!input.email || !input.password) { + throw new Error("Por favor prencha todos os campos."); + }; + const user = await getUserByEmail(input.email); + if (!user) { + throw new Error("Usuario não encontrado!"); + }; + const passwordIsCorrect: boolean = await compare( + input.password, + user.password + ); + if (!passwordIsCorrect) { + throw new Error("Senha incorreta."); + }; + const token = generateToken({ id: user.id }); + res.status(200).send({ acess_token: token }); + } catch (error) { + res.status(400).send({ message: error.message }); + }; +}; \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/endpoints/signup.ts b/Backend/Semana4/projeto_cookenu/src/endpoints/signup.ts new file mode 100644 index 0000000..b0bc3cc --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/endpoints/signup.ts @@ -0,0 +1,49 @@ +import { Request, Response } from "express"; +import insertUser from "../data/insertUser"; +import { generateToken } from "../services/authenticator"; +import { hash } from "../services/hashManager"; +import { generateId } from "../services/idGenerator"; + +export default async function createUser( + req: Request, + res: Response +) { + try { + const password = req.body.password + + if(password.length < 6){ + + throw new Error("O password precisa ter pelo menos 6 caracteres."); + + } + + if ( + !req.body.name || + !req.body.email || + !req.body.password + ) { + throw new Error('Preencha os campos "name","nickname", "email" e "password"') + } + const id: string = generateId() + const cypherPassword = await hash(req.body.password); + await insertUser( + id, + req.body.name, + req.body.email, + cypherPassword, + ) + const token: string = generateToken({ + id + }) + res + .status(201) + .send({ + message: "Usuário criado!", + token + }) + } catch (error) { + res.status(400).send({ + message: error.message || error.sqlMessage + }) + } +} \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/index.ts b/Backend/Semana4/projeto_cookenu/src/index.ts new file mode 100644 index 0000000..d691276 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/index.ts @@ -0,0 +1,42 @@ +import express, { Express, Request, Response } from "express"; +import cors from "cors"; +import { AddressInfo } from "net"; +import knex from "knex"; +import dotenv from "dotenv" +import insertUser from "./data/insertUser"; +import createUser from "./endpoints/signup"; +import { login } from "./endpoints/login"; + +dotenv.config(); + +const app: Express = express(); + +app.use(express.json()); +app.use(cors()); + +export const connection = knex({ + client: "mysql", + connection: { + host: process.env.DB_HOST, + port: 3306, + user: process.env.DB_USER, + password: process.env.DB_PASS, + database: process.env.DB_NAME + } +}); + +app.post('/user/signup', createUser) +app.post('/user/login', login) +app.post('/recipe') +app.get('/user/profile') +app.get('/user/:id') +app.get('/recipe/:id') + +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.`); + } +}); \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/services/authenticator.ts b/Backend/Semana4/projeto_cookenu/src/services/authenticator.ts new file mode 100644 index 0000000..f5c000d --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/services/authenticator.ts @@ -0,0 +1,19 @@ +import * as jwt from "jsonwebtoken" +// import { USER_ROLES } from "../data/insertUser" + +export type AuthenticationData = { + id: string, + // role: USER_ROLES +} + +export function generateToken( + payload: AuthenticationData +): string { + return jwt.sign( + payload, + process.env.JWT_KEY as string, + { + expiresIn: "24min" + } + ) +} \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/services/hashManager.ts b/Backend/Semana4/projeto_cookenu/src/services/hashManager.ts new file mode 100644 index 0000000..3a8d52a --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/services/hashManager.ts @@ -0,0 +1,11 @@ +import * as bcrypt from 'bcryptjs'; + +export const hash = async (plainText: string): Promise => { + const rounds = Number(process.env.BCRYPT_COST); + const salt = await bcrypt.genSalt(rounds); + return bcrypt.hash(plainText, salt) +} + +export const compare = async (plainText: string, cypherText: string): Promise => { + return bcrypt.compare(plainText, cypherText) +} \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/services/idGenerator.ts b/Backend/Semana4/projeto_cookenu/src/services/idGenerator.ts new file mode 100644 index 0000000..d905887 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/services/idGenerator.ts @@ -0,0 +1,5 @@ +import { v4 } from "uuid" + +export const generateId = (): string => { + return v4() +} \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/types/loginInput.ts b/Backend/Semana4/projeto_cookenu/src/types/loginInput.ts new file mode 100644 index 0000000..7a2ad29 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/types/loginInput.ts @@ -0,0 +1,4 @@ +export type loginInput = { + email: string, + password: string +} \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/src/types/user.ts b/Backend/Semana4/projeto_cookenu/src/types/user.ts new file mode 100644 index 0000000..eda4b97 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/src/types/user.ts @@ -0,0 +1,6 @@ +export type user = { + id: string, + name: string, + email: string, + password: string +} \ No newline at end of file diff --git a/Backend/Semana4/projeto_cookenu/tsconfig.json b/Backend/Semana4/projeto_cookenu/tsconfig.json new file mode 100644 index 0000000..b062476 --- /dev/null +++ b/Backend/Semana4/projeto_cookenu/tsconfig.json @@ -0,0 +1,70 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./build", /* Redirect output structure to the directory. */ + "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +}