From 0c693e1bacb9f7a9104b70cf8a815d332f83a612 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Sat, 12 Oct 2024 13:04:51 +0300 Subject: [PATCH 1/2] Cats backend routes --- .../routers/epja-2024-1/cats/admin/index.js | 146 ++++++++++++++++++ server/routers/epja-2024-1/cats/auth/index.js | 15 ++ server/routers/epja-2024-1/cats/data.json | 118 ++++++++++++++ server/routers/epja-2024-1/cats/index.js | 11 ++ server/routers/epja-2024-1/cats/root/index.js | 45 ++++++ server/routers/epja-2024-1/index.js | 2 + 6 files changed, 337 insertions(+) create mode 100644 server/routers/epja-2024-1/cats/admin/index.js create mode 100644 server/routers/epja-2024-1/cats/auth/index.js create mode 100644 server/routers/epja-2024-1/cats/data.json create mode 100644 server/routers/epja-2024-1/cats/index.js create mode 100644 server/routers/epja-2024-1/cats/root/index.js diff --git a/server/routers/epja-2024-1/cats/admin/index.js b/server/routers/epja-2024-1/cats/admin/index.js new file mode 100644 index 0000000..351bd19 --- /dev/null +++ b/server/routers/epja-2024-1/cats/admin/index.js @@ -0,0 +1,146 @@ +const adminRouter = require('express').Router(); +const fs = require('fs'); +const path = require('path'); +require('dotenv').config(); + +const dataFilePath = path.join(__dirname, '../data.json'); +let data = require('../data.json'); + +const verifyToken = (req, res, next) => { + const token = req.headers['authorization']; + if (token === process.env.TOKEN) { + next(); + } else { + res.status(403).send({ 'status': 'Failed', 'data': 'Invalid token' }); + } +}; + +const saveData = (data) => { + fs.writeFileSync(dataFilePath, JSON.stringify(data, null, 2), 'utf-8'); +}; + +adminRouter.post('/edit/nickname', verifyToken, (req, res) => { + const { name, colored } = req.body; + if (!name || !colored) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Nickname is required' }); + } + + data.nickname = { name, colored }; + saveData(data); + + res.status(200).send({ 'status': 'OK', 'data': 'Nickname updated successfully' }); +}); + +adminRouter.post('/edit/tech-stack', verifyToken, (req, res) => { + const { techStack } = req.body; + if (!techStack || !Array.isArray(techStack)) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Valid tech stack is required' }); + } + + data.techStack = techStack; + saveData(data); + + res.status(200).send({ 'status': 'OK', 'data': 'Tech stack updated successfully' }); +}); + +adminRouter.post('/edit/city', verifyToken, (req, res) => { + const { city } = req.body; + if (!city) { + return res.status(400).send({ 'status': 'Failed', 'data': 'City is required' }); + } + + const isValid = typeof city === 'object' && 'name' in city && 'href' in city; + + if (!isValid) { + return res.status(400).send({ 'status': 'Failed', 'data': 'City must contain href and name' }); + } + + data.city = city; + saveData(data); + + res.status(200).send({ 'status': 'OK', 'data': 'City updated successfully' }); +}); + +adminRouter.post('/edit/github-repo', verifyToken, (req, res) => { + const { github } = req.body; + if (!github) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Github is required' }); + } + + const isValid = typeof github === 'object' && 'author' in github && 'repo' in github; + + if (!isValid) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Github must contain author and repo' }); + } + + data.githubRepo = github; + saveData(data); + + res.status(200).send({ 'status': 'OK', 'data': 'Github updated successfully' }); +}); + +adminRouter.post('/edit/nav-links', verifyToken, (req, res) => { + const { navLinks } = req.body; + if (!navLinks || !Array.isArray(navLinks)) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Valid navLinks are required' }); + } + + const isValid = navLinks.every(link => + link && typeof link === 'object' && 'href' in link && 'title' in link + ); + + if (!isValid) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Each navLink must contain href and title' }); + } + + data.navLinks = navLinks; + saveData(data); + + res.status(200).send({ 'status': 'OK', 'data': 'Navigation links updated successfully' }); +}); + +adminRouter.post('/edit/links', verifyToken, (req, res) => { + const { links } = req.body; + if (!links || !Array.isArray(links)) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Valid links are required' }); + } + + const isValid = links.every(link => + link && typeof link === 'object' && 'href' in link && 'title' in link + ); + + if (!isValid) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Each link must contain href and title' }); + } + + data.links = links; + saveData(data); + + res.status(200).send({ 'status': 'OK', 'data': 'Links updated successfully' }); +}); + +adminRouter.post('/edit/projects', verifyToken, (req, res) => { + const { projects } = req.body; + if (!projects) { + return res.status(400).send({ 'status': 'Failed', 'data': 'Projects are required' }); + } + + const projectFields = ['id', 'title', 'description', 'link', 'techStack', 'image']; + + const isValidProject = (project) => { + return projectFields.every(field => field && field in project); + } + + const allProjectsValid = projects.every(project => isValidProject(project)); + + if (!allProjectsValid) { + return res.status(400).send({ 'status': 'Failed', 'data': 'All projects must contain ' + projectFields.join(", ") }); + } + + data.projects = projects; + saveData(data); + + res.status(200).send({ 'status': 'OK', 'data': 'Projects updated successfully' }); +}); + +module.exports = adminRouter; diff --git a/server/routers/epja-2024-1/cats/auth/index.js b/server/routers/epja-2024-1/cats/auth/index.js new file mode 100644 index 0000000..933c810 --- /dev/null +++ b/server/routers/epja-2024-1/cats/auth/index.js @@ -0,0 +1,15 @@ +const authRouter = require('express').Router(); +require('dotenv').config(); + +module.exports = authRouter; + +authRouter.post('/login', (req, res) => { + const { email, password } = req.body; + console.log(`Login with email=${email} and password=${password}`); + + if (email === 'admin@admin.admin' && password === 'admin') { + res.status(200).send({ 'status': 'OK', 'data': `${process.env.TOKEN}` }); + } else { + res.status(401).send({ 'status': 'Failed!', 'data': 'Invalid email or password' }); + } +}); diff --git a/server/routers/epja-2024-1/cats/data.json b/server/routers/epja-2024-1/cats/data.json new file mode 100644 index 0000000..415b841 --- /dev/null +++ b/server/routers/epja-2024-1/cats/data.json @@ -0,0 +1,118 @@ +{ + "nickname": { + "name": "supercool", + "colored": "nickname" + }, + "techStack": [ + "React", + "Next.js", + "Svelte", + "SvelteKit", + "HTML", + "CSS", + "JavaScript", + "TypeScript", + "TailwindCSS", + "Styled-Components", + "Framer-Motion", + "shadcn-ui", + "Ant-Design", + "ESLint", + "Prettier", + "husky", + "lint-staged", + "Redux", + "RTK Query", + "Tanstack Query", + "Python", + "FastApi", + "Flask", + "SQLite", + "PostgreSQL", + "MongoDB", + "SQLAlchemy", + "Alembic", + "PyPy", + "poetry", + "pylint", + "GitHub Actions", + "GitLab CI/CD", + "Docker", + "Git" + ], + "githubRepo": { + "author": "MishaBlin", + "repo": "EPJA_portfolio_app" + }, + "city": { + "name": "Innopolis", + "href": "https://ru.wikipedia.org/wiki/Иннополис" + }, + "navLinks": [ + { + "href": "#about", + "title": "About" + }, + { + "href": "#projects", + "title": "Projects" + } + ], + "links": [ + { + "href": "mailto:svyatoslavsvyatkin@yandex.ru", + "title": "Mail" + }, + { + "href": "https://t.me/dmhd6219", + "title": "Telegram" + }, + { + "href": "https://github.com/dmhd6219", + "title": "GitHub" + }, + { + "href": "https://last.fm/user/dmhd", + "title": "LastFm" + }, + { + "href": "https://pay.cloudtips.ru/p/02da9349", + "title": "Buy me a coffee" + } + ], + "projects": [ + { + "title": "Elasticsearch", + "description": "Elasticsearch is a distributed search and analytics engine, scalable data store and vector database optimized for speed and relevance on production-scale workloads.", + "link": "https://github.com/elastic/elasticsearch", + "techStack": [ + "Java", + "Groovy" + ], + "image": "https://datascientest.com/en/files/2023/04/Elasticsearch.jpg", + "id": "elasticsearch" + }, + { + "title": "React-native", + "description": "React Native brings React's declarative UI framework to iOS and Android. With React Native, you use native UI controls and have full access to the native platform.", + "link": "https://github.com/facebook/react-native", + "techStack": [ + "C++", + "Javascript", + "Kotlin" + ], + "image": "https://www.simplilearn.com/ice9/free_resources_article_thumb/React_Native_Tutorial.jpg", + "id": "react-native" + }, + { + "title": "Zarr", + "description": "Zarr is a Python package providing an implementation of compressed, chunked, N-dimensional arrays, designed for use in parallel computing. See the documentation for more information.", + "link": "https://github.com/zarr-developers/zarr-python", + "techStack": [ + "Python" + ], + "image": "https://raw.githubusercontent.com/zarr-developers/community/main/logos/logo2.png", + "id": "zarr" + } + ] +} \ No newline at end of file diff --git a/server/routers/epja-2024-1/cats/index.js b/server/routers/epja-2024-1/cats/index.js new file mode 100644 index 0000000..b63490c --- /dev/null +++ b/server/routers/epja-2024-1/cats/index.js @@ -0,0 +1,11 @@ +const authRouter = require('./auth'); +const adminRouter = require('./admin'); +const rootRouter = require('./root'); + +const router = require('express').Router(); + +module.exports = router; + +router.use(`/auth`, authRouter); +router.use(`/admin`, adminRouter); +router.use(`/`, rootRouter); \ No newline at end of file diff --git a/server/routers/epja-2024-1/cats/root/index.js b/server/routers/epja-2024-1/cats/root/index.js new file mode 100644 index 0000000..0bfc9a7 --- /dev/null +++ b/server/routers/epja-2024-1/cats/root/index.js @@ -0,0 +1,45 @@ +const rootRouter = require('express').Router(); +require('dotenv').config(); +const data = require('../data.json'); + +rootRouter.get('/get/nickname', (req, res) => { + res.status(200).send({ 'status': 'OK', 'data': data.nickname }); +}); + +rootRouter.get('/get/tech-stack', (req, res) => { + res.status(200).send({ 'status': 'OK', 'data': data.techStack }); +}); + +rootRouter.get('/get/github-repo', (req, res) => { + res.status(200).send({ 'status': 'OK', 'data': data.githubRepo }); +}); + +rootRouter.get('/get/city', (req, res) => { + res.status(200).send({ 'status': 'OK', 'data': data.city }); +}); + +rootRouter.get('/get/nav-links', (req, res) => { + res.status(200).send({ 'status': 'OK', 'data': data.navLinks }); +}); + +rootRouter.get('/get/links', (req, res) => { + res.status(200).send({ 'status': 'OK', 'data': data.links }); +}); + +rootRouter.get('/get/projects', (req, res) => { + res.status(200).send({ 'status': 'OK', 'data': data.projects }); +}); + +rootRouter.get('/get/projects/:id', (req, res) => { + const { id } = req.params; + const project = data.projects.find(p => p.id === id); + + if (project) { + res.status(200).send({ status: 'OK', data: project }); + } else { + res.status(404).send({ status: 'NOT_FOUND', message: 'Project not found' }); + } +}); + + +module.exports = rootRouter; \ No newline at end of file diff --git a/server/routers/epja-2024-1/index.js b/server/routers/epja-2024-1/index.js index 2097192..232b81d 100644 --- a/server/routers/epja-2024-1/index.js +++ b/server/routers/epja-2024-1/index.js @@ -4,4 +4,6 @@ const router = express.Router() router.use('/enterfront', require('./enterfront/index')) +router.use('/cats', require('./cats/index')) + module.exports = router From 528b37246b4c1ce179092fe29c64b17a7c2fe5e9 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Sat, 12 Oct 2024 13:23:16 +0300 Subject: [PATCH 2/2] Const file for token --- server/routers/epja-2024-1/cats/admin/index.js | 3 ++- server/routers/epja-2024-1/cats/auth/index.js | 5 +++-- server/routers/epja-2024-1/cats/const.js | 3 +++ server/routers/epja-2024-1/cats/root/index.js | 1 - 4 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 server/routers/epja-2024-1/cats/const.js diff --git a/server/routers/epja-2024-1/cats/admin/index.js b/server/routers/epja-2024-1/cats/admin/index.js index 351bd19..66d8af9 100644 --- a/server/routers/epja-2024-1/cats/admin/index.js +++ b/server/routers/epja-2024-1/cats/admin/index.js @@ -1,6 +1,7 @@ const adminRouter = require('express').Router(); const fs = require('fs'); const path = require('path'); +const { TOKEN } = require('../const'); require('dotenv').config(); const dataFilePath = path.join(__dirname, '../data.json'); @@ -8,7 +9,7 @@ let data = require('../data.json'); const verifyToken = (req, res, next) => { const token = req.headers['authorization']; - if (token === process.env.TOKEN) { + if (token === TOKEN) { next(); } else { res.status(403).send({ 'status': 'Failed', 'data': 'Invalid token' }); diff --git a/server/routers/epja-2024-1/cats/auth/index.js b/server/routers/epja-2024-1/cats/auth/index.js index 933c810..51a26a7 100644 --- a/server/routers/epja-2024-1/cats/auth/index.js +++ b/server/routers/epja-2024-1/cats/auth/index.js @@ -1,5 +1,6 @@ const authRouter = require('express').Router(); -require('dotenv').config(); +const { TOKEN } = require('../const'); + module.exports = authRouter; @@ -8,7 +9,7 @@ authRouter.post('/login', (req, res) => { console.log(`Login with email=${email} and password=${password}`); if (email === 'admin@admin.admin' && password === 'admin') { - res.status(200).send({ 'status': 'OK', 'data': `${process.env.TOKEN}` }); + res.status(200).send({ 'status': 'OK', 'data': `${TOKEN}` }); } else { res.status(401).send({ 'status': 'Failed!', 'data': 'Invalid email or password' }); } diff --git a/server/routers/epja-2024-1/cats/const.js b/server/routers/epja-2024-1/cats/const.js new file mode 100644 index 0000000..7e32060 --- /dev/null +++ b/server/routers/epja-2024-1/cats/const.js @@ -0,0 +1,3 @@ +const TOKEN = "ASDFGHJKLLKJHGFDSDFGHJKJHGF"; + +module.exports = { TOKEN } \ No newline at end of file diff --git a/server/routers/epja-2024-1/cats/root/index.js b/server/routers/epja-2024-1/cats/root/index.js index 0bfc9a7..ad2b541 100644 --- a/server/routers/epja-2024-1/cats/root/index.js +++ b/server/routers/epja-2024-1/cats/root/index.js @@ -1,5 +1,4 @@ const rootRouter = require('express').Router(); -require('dotenv').config(); const data = require('../data.json'); rootRouter.get('/get/nickname', (req, res) => {