diff --git a/backend/config/config.js b/backend/config/config.js deleted file mode 100644 index 8cad812b..00000000 --- a/backend/config/config.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - "development": { - "username": process.env.DB_USERNAME, - "password": process.env.DB_PASSWORD, - "database":process.env.DB_NAME, - "host": "127.0.0.1", - "dialect": "mysql" - }, - "test": { - "username": "root", - "password": null, - "database": "database_test", - "host": "127.0.0.1", - "dialect": "mysql" - }, - "production": { - "username": "root", - "password": null, - "database": "database_production", - "host": "127.0.0.1", - "dialect": "mysql" - } -} diff --git a/backend/config/config.json b/backend/config/config.json index 1d12efbb..00939f6b 100644 --- a/backend/config/config.json +++ b/backend/config/config.json @@ -1,8 +1,8 @@ { "development": { "username": "root", - "password": "password", - "database": "matriculai_development", + "password": "julia12345", + "database": "matriculai", "host": "localhost", "dialect": "mysql" }, diff --git a/backend/controllers/ElectiveControllers.js b/backend/controllers/ElectiveControllers.js index 34db7430..25a8a9e3 100644 --- a/backend/controllers/ElectiveControllers.js +++ b/backend/controllers/ElectiveControllers.js @@ -1,9 +1,7 @@ const { Electives } = require('../models/schemas') - exports.createElective = async(req, res) => { - const { name, description, school_year, teacher, vacancies, schedules } = req.body - + const { name, description, school_year, teacher, vacancies, schedules } = req.body; await Electives.create({ name: name, description: description, @@ -15,18 +13,18 @@ exports.createElective = async(req, res) => { res.status(201).json("OK") }).catch((err) => { if(err){ - res.status(400).json({error: err}) - } - }) -} + res.status(400).json({error: err}); + }; + }); +}; exports.deleteElective = async(req, res) => { const { id } = req.body await Electives.destroy({ where: {id: id}}).then(() => { - res.status(200).json("OK") + res.status(200).json("OK"); }).catch((err) => { if(err){ - res.status(400).json({error: err}) - } - }) -} \ No newline at end of file + res.status(400).json({error: err}); + }; + }); +}; \ No newline at end of file diff --git a/backend/controllers/LearningPathsController.js b/backend/controllers/LearningPathsController.js index 6288c2c5..277bb464 100644 --- a/backend/controllers/LearningPathsController.js +++ b/backend/controllers/LearningPathsController.js @@ -1,8 +1,8 @@ const { LearningPath } = require('../models/schemas') exports.createLearningPaths = async(req, res) => { - const { name, description, school_year, electives} = req.body - let electives_object = JSON.stringify(electives) + const { name, description, school_year, electives} = req.body; + let electives_object = JSON.stringify(electives); await LearningPath.create({ name: name, @@ -14,17 +14,17 @@ exports.createLearningPaths = async(req, res) => { }).catch((err) => { if(err){ res.status(400).json({error: err}) - } - }) -} + }; + }); +}; exports.deleteLearningPaths = async(req, res) => { - const { id } = req.body + const { id } = req.body; await LearningPath.destroy({ where: {id: id}}).then(() => { - res.status(200).json("OK") + res.status(200).json("OK"); }).catch((err) => { if(err){ - res.status(400).json({error: err}) - } - }) -} \ No newline at end of file + res.status(400).json({error: err}); + }; + }); +}; \ No newline at end of file diff --git a/backend/controllers/UserControllers.js b/backend/controllers/UserControllers.js index 5d9af214..c7c0dc41 100644 --- a/backend/controllers/UserControllers.js +++ b/backend/controllers/UserControllers.js @@ -1,48 +1,59 @@ const { Users } = require('../models/schemas'); const bcrypt = require('bcrypt'); -const { sign } = require('jsonwebtoken'); const { createToken, validateToken } = require('./middlewares/Auth'); -exports.userRegister = async(req, res) => { - const { email, password } = req.body; - bcrypt.hash(password, 15).then((hash) => { - Users.create({ +exports.userRegister = async (req, res) => { + try { + const { email, password } = req.body; + const existingUser = await Users.findOne({ where: { email: email } }); + + if (existingUser) { + return res.status(400).json({ error: 'E-mail já cadastrado!' }); + } + + const hash = await bcrypt.hash(password, 15); + await Users.create({ email: email, password: hash, - }).then(() =>{ - res.json('Solicitação bem sucedida!'); - }).catch((err) => { - if(err){ - res.status(400).json({error: err}); - } }); - }); + + res.json('Solicitação bem sucedida!'); + } catch (err) { + res.status(400).json({ error: err.message || 'Erro desconhecido durante o registro.' }); + } }; -exports.userLogin = async(req, res) => { - const { email, password } = req.body; - const user = await Users.findOne({where: {email: email}}); - if(!user){ - res.status(400).json({error: 'E-mail não cadastrado!'}); - } else { - bcrypt.compare(password, user.password).then((match) =>{ - if(!match){ - res.status(400).json({error: 'Senha incorreta!'}); - } else { - const accessToken = createToken(user); - res.cookie('access-token', accessToken, { - maxAge: 2592000000, - httpOnly: true, - }); - Users.update( - { token: accessToken }, - { where: { email: user.email } } - ).then(() => { - res.json(accessToken); - }).catch((err) => { - res.status(500).json({ error: 'Erro ao atualizar o token no banco de dados.' }); - }); - }; +exports.userLogin = async (req, res) => { + try { + const { email, password } = req.body; + const user = await Users.findOne({ where: { email: email } }); + + if (!user) { + return res.status(400).json({ error: 'E-mail não cadastrado!' }); + } + + const match = await bcrypt.compare(password, user.password); + + if (!match) { + return res.status(400).json({ error: 'Senha incorreta!' }); + } + + const accessToken = createToken(user); + + await Users.update( + { token: accessToken }, + { where: { email: user.email } } + ); + + res.cookie('access-token', accessToken, { + maxAge: 2592000000, // 30 dias em milissegundos + httpOnly: true, + secure: true, }); - }; -}; \ No newline at end of file + + res.json({ accessToken: accessToken }); + } catch (err) { + console.error(err); + res.status(500).json({ error: 'Erro durante o login.' }); + } +}; diff --git a/backend/controllers/middlewares/Auth.js b/backend/controllers/middlewares/Auth.js index 33eea256..3b3a3b9e 100644 --- a/backend/controllers/middlewares/Auth.js +++ b/backend/controllers/middlewares/Auth.js @@ -8,20 +8,21 @@ const createToken = (user) => { }; const validateToken = (req, res, next) => { - const accessToken = req.cookies['access-token']; - if(!accessToken) { //vê se o user já foi autenticado pelo cookie de sessão - return res.status(400).json({error: 'Usuário não autenticado!'}); - }; - + + const accessToken = req.cookies && req.cookies['access-token']; + if (!accessToken) { + return res.status(400).json({ error: 'Usuário não autenticado!' }); + } + try { const validToken = verify(accessToken, process.env.SECRET); - if(validToken){ + if (validToken) { req.authenticated = true; return next(); } - } catch(err) { - return res.status(400).json({error: err}); - }; + } catch (err) { + return res.status(400).json({ error: err.message || 'Erro na validação do token' }); + } }; module.exports = { createToken, validateToken }; diff --git a/backend/index.js b/backend/index.js index 63240aa5..67afc75f 100644 --- a/backend/index.js +++ b/backend/index.js @@ -1,5 +1,5 @@ -const { validateToken } = require('./controllers/middlewares/Auth'); const express = require('express'); +const cors = require('cors'); const database = require('./models/schemas'); const userRoute = require('./views/routes/Users'); const electiveRoute = require('./views/routes/Electives') @@ -9,9 +9,9 @@ require("dotenv").config(); const app = express(); const port = 3001; app.use(express.json()); -app.use(validateToken); +app.use(cors()); -app.use(userRoute); +app.use('/auth', userRoute); app.use('/elective', electiveRoute); app.use('/learning_paths', learningPathRoute); diff --git a/backend/views/routes/Electives.js b/backend/views/routes/Electives.js index 07dbf7d7..55b9005a 100644 --- a/backend/views/routes/Electives.js +++ b/backend/views/routes/Electives.js @@ -3,6 +3,6 @@ const router = express.Router(); const electivesController = require('../../controllers/ElectiveControllers') router.post("/createElective", electivesController.createElective); -router.delete("/", electivesController.deleteElective) +router.delete("/deleteElective", electivesController.deleteElective) module.exports = router; diff --git a/backend/views/routes/LearningPaths.js b/backend/views/routes/LearningPaths.js index 75c075c3..51588998 100644 --- a/backend/views/routes/LearningPaths.js +++ b/backend/views/routes/LearningPaths.js @@ -3,6 +3,6 @@ const router = express.Router(); const learningPathsController = require('../../controllers/LearningPathsController') router.post("/createLearningPaths", learningPathsController.createLearningPaths); -router.delete("/", learningPathsController.deleteLearningPaths) +router.delete("/deleteLearningPaths", learningPathsController.deleteLearningPaths) module.exports = router; diff --git a/backend/views/routes/Users.js b/backend/views/routes/Users.js index 544d685a..ccbe2d81 100644 --- a/backend/views/routes/Users.js +++ b/backend/views/routes/Users.js @@ -1,15 +1,16 @@ const express = require('express'); const router = express.Router(); const cookieParser = require('cookie-parser'); -const userController = require('../../controllers/UserControllers'); +const userController = require('../../controllers/UserControllers'); const { validateToken } = require('../../controllers/middlewares/Auth'); router.use(cookieParser()); -router.post('/', userController.userRegister); -router.post('/login', userController.userLogin); router.get('/profile', validateToken, (req, res) => { res.json('profile'); }); -module.exports = router; +router.post('/register', userController.userRegister); +router.post('/login', userController.userLogin); + +module.exports = router; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5a6a2d6e..e625e4c8 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14,6 +14,7 @@ "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^13.0.0", "@testing-library/user-event": "^13.2.1", + "axios": "^1.6.2", "framer-motion": "^10.16.4", "react": "^18.0.0", "react-dom": "^18.0.0", @@ -6690,6 +6691,29 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -10184,24 +10208,22 @@ } }, "node_modules/follow-redirects": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.10.0.tgz", - "integrity": "sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==", - "license": "MIT", - "dependencies": { - "debug": "^3.0.0" - }, + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { "node": ">=4.0" - } - }, - "node_modules/follow-redirects/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, "node_modules/fork-ts-checker-webpack-plugin": { @@ -15494,6 +15516,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index d5a3318a..61ff5b78 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,6 +9,7 @@ "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^13.0.0", "@testing-library/user-event": "^13.2.1", + "axios": "^1.6.2", "framer-motion": "^10.16.4", "react": "^18.0.0", "react-dom": "^18.0.0", diff --git a/frontend/src/icon/definicoes 1.png b/frontend/src/icon/definicoes 1.png new file mode 100644 index 00000000..53c647fc Binary files /dev/null and b/frontend/src/icon/definicoes 1.png differ diff --git a/frontend/src/icon/interrogatorio 1.png b/frontend/src/icon/interrogatorio 1.png new file mode 100644 index 00000000..43991309 Binary files /dev/null and b/frontend/src/icon/interrogatorio 1.png differ diff --git a/frontend/src/icon/sair-alt 1.png b/frontend/src/icon/sair-alt 1.png new file mode 100644 index 00000000..c5476996 Binary files /dev/null and b/frontend/src/icon/sair-alt 1.png differ diff --git a/frontend/src/icon/usuario-do-circulo 1.png b/frontend/src/icon/usuario-do-circulo 1.png new file mode 100644 index 00000000..a3b7025b Binary files /dev/null and b/frontend/src/icon/usuario-do-circulo 1.png differ diff --git a/frontend/src/pages/Home/index.js b/frontend/src/pages/Home/index.js index 54482ae1..92dfa9c4 100644 --- a/frontend/src/pages/Home/index.js +++ b/frontend/src/pages/Home/index.js @@ -1,11 +1,37 @@ import React from "react"; +import styled from "styled-components"; import { Link } from "react-router-dom"; -import { Flex, Box, Heading, Spacer, Text, Center, Menu, MenuButton, MenuList, MenuItem, Button} from "@chakra-ui/react"; // Importe os componentes do Chakra UI ou outro framework que você esteja usando +import { Flex, Box, Heading, Spacer, Menu, MenuButton, MenuList, MenuItem } from "@chakra-ui/react"; import { Image } from '@chakra-ui/react' import cmtnLogo from '../../img/cmtnLogo.png' import menuHamburguer from '../../icon/menuHamburguer.png' +import userIcon from '../../icon/usuario-do-circulo 1.png'; +import settingsIcon from '../../icon/definicoes 1.png'; +import helpIcon from '../../icon/interrogatorio 1.png'; +import logoutIcon from '../../icon/sair-alt 1.png'; const Header = () => { + const StyledMenuList = styled(MenuList)` + list-style: 'circle'; + padding: 0; + margin: 0; + `; + + const StyledMenuItem = styled(MenuItem)` + display: flex; + align-items: center; + margin-bottom: 10px; + color: white; /* Cor azul para o texto */ + font-family: Arial, sans-serif; /* Altera a fonte */ + background-color: #243A69; + `; + + const StyledImage = styled(Image)` + max-width: 24px; + max-height: 24px; + margin-right: 10px; /* Adiciona um espaçamento entre a imagem e o texto */ + `; + return ( { Home - + - - menuHamburguer + menuHamburguer - - Download - Create a Copy - Mark as Draft - Delete - Attend a Workshop - + + + + Conta + + + + Configuração + + + + Ajuda + + + + Sair + + - + ); diff --git a/frontend/src/pages/Signin/index.js b/frontend/src/pages/Signin/index.js index 08f3ac73..20a41a20 100644 --- a/frontend/src/pages/Signin/index.js +++ b/frontend/src/pages/Signin/index.js @@ -20,31 +20,26 @@ const Signin = () => { const [error, setError] = useState(""); const handleLogin = async () => { - if (!email || !senha) { - setError("Preencha todos os campos"); - return; - } - console.log(email); - console.log(senha); try { - const response = await axios.post('localhost:3000', { email, senha }); - - if (response.status === 200) { - // Sucesso, redirecionar ou realizar outras ações necessárias + const response = await axios.post("http://localhost:3001/auth/login", { + email: email, + password: senha, + }); + + if (response.data.accessToken) { + signin(response.data.accessToken); navigate("/home"); } else { - // Exibir mensagem de erro - setError(response.data.message); + setError("Credenciais inválidas"); } } catch (error) { - if (axios.isAxiosError(error)) { - // Imprime informações detalhadas sobre o erro Axios - console.error("Erro ao fazer login - Status:", error.response?.status); - console.error("Erro ao fazer login - Data:", error.response?.data); + console.error("Error during login:", error); + if (error.response) { + console.error("Server response:", error.response.data); + setError(error.response.data.error || "Erro durante o login"); } else { - console.error("Erro ao fazer login:", error); + setError("Erro durante o login"); } - setError("Erro ao fazer login. Tente novamente mais tarde."); } }; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 778eb856..e03eeb6b 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -3747,6 +3747,15 @@ axe-core@^4.3.5: resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz" integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw== +axios@^1.6.2: + version "1.6.2" + resolved "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz" + integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz" @@ -4710,13 +4719,6 @@ debug@^2.6.9: dependencies: ms "2.0.0" -debug@^3.0.0: - version "3.2.6" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - debug@^3.1.1: version "3.2.6" resolved "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz" @@ -5700,12 +5702,10 @@ focus-lock@^1.0.0: dependencies: tslib "^2.0.3" -follow-redirects@^1.0.0: - version "1.10.0" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.10.0.tgz" - integrity sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ== - dependencies: - debug "^3.0.0" +follow-redirects@^1.0.0, follow-redirects@^1.15.0: + version "1.15.3" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz" + integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== fork-ts-checker-webpack-plugin@^6.5.0: version "6.5.1" @@ -5735,6 +5735,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" @@ -8630,6 +8639,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + psl@^1.1.33: version "1.8.0" resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz"