diff --git a/client.mjs b/client.mjs index a05a777..781abe3 100644 --- a/client.mjs +++ b/client.mjs @@ -1,186 +1,220 @@ export class Client { - /** - * Должен возвращать имя пользователя или null - * если пользователь не залогинен - * - * @return {Promise} username - * */ - async getUser() { - throw new Error("Not implemented"); - } + /** + * Должен возвращать имя пользователя или null + * если пользователь не залогинен + * + * @return {Promise} username + * */ + async getUser() { + return fetch('api/user').then(async res => { + return Promise.resolve(res.text()); + }); + } - /** - * Должен логинить пользователя с именем username - * и возвращать его имя - * - * @param {string} username - * @return {Promise} username - * */ - async loginUser(username) { - throw new Error("Not implemented"); - } + /** + * Должен логинить пользователя с именем username + * и возвращать его имя + * + * @param {string} username + * @return {Promise} username + * */ + async loginUser(username) { + return fetch(`api/login?username=${username}`).then(async res => { + return Promise.resolve(res.text()); + }); + } - /** - * Должен разлогинивать текущего пользователя - * - * @return {void} - * */ - async logoutUser() { - throw new Error("Not implemented"); - } + /** + * Должен разлогинивать текущего пользователя + * + * @return {void} + * */ + async logoutUser() { + await fetch('api/logout'); + } - /** - * Должен возвращать информацию о компании - * - * @typedef {Object} Headquarters - * @property {string} address - * @property {string} city - * @property {string} state - * - * @typedef {Object} About - * @property {string} founder - * @property {string} founded - * @property {number} employees - * @property {string} ceo - * @property {string} coo - * @property {string} cto - * @property {number} valuation - * @property {Headquarters} headquarters - * @property {string} summary - * @return {Promise} - * */ - async getInfo() { - throw new Error("Not implemented"); - } + /** + * Должен возвращать информацию о компании + * + * @typedef {Object} Headquarters + * @property {string} address + * @property {string} city + * @property {string} state + * + * @typedef {Object} About + * @property {string} founder + * @property {string} founded + * @property {number} employees + * @property {string} ceo + * @property {string} coo + * @property {string} cto + * @property {number} valuation + * @property {Headquarters} headquarters + * @property {string} summary + * @return {Promise} + * */ + async getInfo() { + const res = await fetch('https://api.spacexdata.com/v3/info'); + if (res.ok) + return Promise.resolve(res.json()); + } - /** - * Должен возвращать информацию о всех событиях - * - * @typedef {Object} EventBrief - * @property {number} id - * @property {string} title - * - * @return {Promise} - * */ - async getHistory() { - throw new Error("Not implemented"); - } + /** + * Должен возвращать информацию о всех событиях + * + * @typedef {Object} EventBrief + * @property {number} id + * @property {string} title + * + * @return {Promise} + * */ + async getHistory() { + const res = await fetch('https://api.spacexdata.com/v3/history'); + if (res.ok) + return Promise.resolve(res.json()); + } - /** - * Должен возвращать информацию о запрошенном событии - * - * @typedef {Object} EventFull - * @property {number} id - * @property {string} title - * @property {string} event_date_utc - * @property {string} details - * @property {Object.} links - * - * @param {number} id - * @return {Promise} - * */ - async getHistoryEvent(id) { - throw new Error("Not implemented"); - } + /** + * Должен возвращать информацию о запрошенном событии + * + * @typedef {Object} EventFull + * @property {number} id + * @property {string} title + * @property {string} event_date_utc + * @property {string} details + * @property {Object.} links + * + * @param {number} id + * @return {Promise} + * */ + async getHistoryEvent(id) { + const res = await fetch(`https://api.spacexdata.com/v3/history/${id}`); + if (res.ok) + return Promise.resolve(res.json()); + } - /** - * Должен возвращать информацию о всех ракетах - * - * @typedef {Object} RocketBrief - * @property {number} rocket_id - * @property {string} rocket_name - * - * @return {Promise} - * */ - async getRockets() { - throw new Error("Not implemented"); - } + /** + * Должен возвращать информацию о всех ракетах + * + * @typedef {Object} RocketBrief + * @property {number} rocket_id + * @property {string} rocket_name + * + * @return {Promise} + * */ + async getRockets() { + const res = await fetch('https://api.spacexdata.com/v3/rockets'); + if (res.ok) + return Promise.resolve(res.json()); + } - /** - * Должен возвращать информацию о запрошенной ракете - * - * @typedef {Object} RocketFull - * @property {number} rocket_id - * @property {string} rocket_name - * @property {string} first_flight - * @property {string} description - * @property {string} wikipedia - * @property {string[]} flickr_images - * Смотри источник данных: - * @property {Object} height - * @property {Object} diameter - * @property {Object} mass - * @property {Object} engines - * @property {Object} first_stage - * @property {Object} second_stage - * - * @param {string} id - * @return {Promise} - * */ - async getRocket(id) { - throw new Error("Not implemented"); - } + /** + * Должен возвращать информацию о запрошенной ракете + * + * @typedef {Object} RocketFull + * @property {number} rocket_id + * @property {string} rocket_name + * @property {string} first_flight + * @property {string} description + * @property {string} wikipedia + * @property {string[]} flickr_images + * Смотри источник данных: + * @property {Object} height + * @property {Object} diameter + * @property {Object} mass + * @property {Object} engines + * @property {Object} first_stage + * @property {Object} second_stage + * + * @param {string} id + * @return {Promise} + * */ + async getRocket(id) { + const res = await fetch(`https://api.spacexdata.com/v3/rockets/${id}`); + if (res.ok) + return Promise.resolve(res.json()); + } - /** - * Должен возвращать информацию о машине в космосе - * - * @typedef {Object} Roadster - * @property {string} name - * @property {string} launch_date_utc - * @property {string} details - * @property {number} earth_distance_km - * @property {number} mars_distance_km - * @property {string} wikipedia - * - * @return {Promise} - * */ - async getRoadster() { - throw new Error("Not implemented"); - } + /** + * Должен возвращать информацию о машине в космосе + * + * @typedef {Object} Roadster + * @property {string} name + * @property {string} launch_date_utc + * @property {string} details + * @property {number} earth_distance_km + * @property {number} mars_distance_km + * @property {string} wikipedia + * + * @return {Promise} + * */ + async getRoadster() { + const res = await fetch('https://api.spacexdata.com/v3/roadster'); + if (res.ok) + return Promise.resolve(res.json()); + } - /** - * Должен возвращать информацию о всех посланных на Марс предметах - * - * @typedef {Object} Item - * @property {!string} id - * @property {!string} name - * @property {!string} phone - * @property {?number} weight - * @property {?string} color - * @property {?boolean} important - * - * @return {Promise} - * */ - async getSentToMars() { - throw new Error("Not implemented"); - } + /** + * Должен возвращать информацию о всех посланных на Марс предметах + * + * @typedef {Object} Item + * @property {!string} id + * @property {!string} name + * @property {!string} phone + * @property {?number} weight + * @property {?string} color + * @property {?boolean} important + * + * @return {Promise} + * */ + async getSentToMars() { + const res = await fetch('api/sendToMars'); + if (res.ok) + return Promise.resolve(res.json()); + } - /** - * Должен посылать на марс переданный предмет и - * возвращать информацию о всех посланных на Марс предметах - * - * @typedef {Object} ItemToSend - * @property {!string} name - * @property {!string} phone - * @property {?number} weight - * @property {?string} color - * @property {?boolean} important - * - * @param {ItemToSend} item - * @return {Promise} - * */ - async sendToMars(item) { - throw new Error("Not implemented"); - } + /** + * Должен посылать на марс переданный предмет и + * возвращать информацию о всех посланных на Марс предметах + * + * @typedef {Object} ItemToSend + * @property {!string} name + * @property {!string} phone + * @property {?number} weight + * @property {?string} color + * @property {?boolean} important + * + * @param {ItemToSend} item + * @return {Promise} + * */ + async sendToMars(item) { + const res = await fetch("/api/sendToMars", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(item), + }); + if (res.ok) + return Promise.resolve(res.json()); + } - /** - * Должен отменять отправку на марс переданного предмета и - * возвращать информацию о всех посланных на Марс предметах - * - * @param {Item} item - * @return {Promise} - * */ - async cancelSendingToMars(item) { - throw new Error("Not implemented"); - } -} + /** + * Должен отменять отправку на марс переданного предмета и + * возвращать информацию о всех посланных на Марс предметах + * + * @param {Item} item + * @return {Promise} + * */ + async cancelSendingToMars(item) { + const res = await fetch("/api/sendToMars", { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(item), + }); + if (res.ok) + return Promise.resolve(res.json()); + } +} \ No newline at end of file diff --git a/server.mjs b/server.mjs index 75d9cbe..8891e9a 100644 --- a/server.mjs +++ b/server.mjs @@ -9,19 +9,94 @@ import fetch from "node-fetch"; const rootDir = process.cwd(); const port = 3000; const app = express(); +const peopleToMars = {}; +let index = 0; + +const checkLogin = function (req, res, next) { + const path = req.path; + if (path !== '/login' && !req.cookies.username) + res.redirect('/login'); + + next(); +}; + +app.use(express.static('spa/build')); //1 +app.use(cookieParser()); //5 +app.use(bodyParser.json()); //7 + +app.get('', (req, res) => { + res.send('spa/build/index.html') +}); app.get("/client.mjs", (_, res) => { - res.header("Cache-Control", "private, no-cache, no-store, must-revalidate"); - res.sendFile(path.join(rootDir, "client.mjs"), { - maxAge: -1, - cacheControl: false, - }); + res.header("Cache-Control", "private, no-cache, no-store, must-revalidate"); + res.sendFile(path.join(rootDir, "client.mjs"), { + maxAge: -1, + cacheControl: false, + }); }); app.get("/", (_, res) => { - res.send(":)"); + res.send(":)"); +}); + +app.get("/api/login", (req, res) => { + const username = req.query.username; + res.cookie('username', username, { httpOnly: true, secure: true, sameSite: 'Strict' }); + res.send(username); +}); + +app.get("/api/logout", (req, res) => { + res.clearCookie('username'); + res.sendStatus(200) +}) + +app.get("/api/user", (req, res) => { + res.send(req.cookies.username); }); -app.listen(port, () => { - console.log(`App listening on port ${port}`); +// 8 +app.get("/api/sendToMars", (req, res) => { + let answer = []; + for (let i in peopleToMars) + answer.push(peopleToMars[i]) + + res.json(answer); +}); + +app.post("/api/sendToMars", (req, res) => { + const item = req.body; + item['id'] = index; + peopleToMars[index++] = item; + let answer = []; + for (let i in peopleToMars) + answer.push(peopleToMars[i]) + + res.json(answer); +}); + +app.delete("/api/sendToMars", (req, res) => { + const item = req.body; + delete peopleToMars[item.id]; + let answer = []; + for (let i in peopleToMars) + answer.push(peopleToMars[i]) + + res.json(answer); }); +//8 + +app.use(checkLogin); +app.get('/*', (req, res) => { + res.sendFile(path.join(rootDir, 'spa/build/index.html')); +}); + +//3 task +https.createServer({ + key: fs.readFileSync("certs/server.key"), + cert: fs.readFileSync("certs/server.cert"), + }, + app +).listen(port, function() { + console.log(`Я работаю здесь: https://localhost:${port}`); +}); \ No newline at end of file