diff options
author | 2020-11-22 13:49:09 +0100 | |
---|---|---|
committer | 2020-11-22 13:49:09 +0100 | |
commit | 4569b85489e863465395f84e995dd3fdc44471b4 (patch) | |
tree | 6e4d27883809c94c8b3f3b87159d85c7f3874bbd | |
parent | 81ddf9b700bc48a1f8e472209f080f9c1d9a9b09 (diff) | |
download | website_creator-4569b85489e863465395f84e995dd3fdc44471b4.tar.gz website_creator-4569b85489e863465395f84e995dd3fdc44471b4.tar.bz2 website_creator-4569b85489e863465395f84e995dd3fdc44471b4.zip |
implement refresh tokens
-rwxr-xr-x | app.js | 8 | ||||
-rw-r--r-- | client/admin/out.js | 30 | ||||
-rw-r--r-- | client/login/out.js | 28 | ||||
-rw-r--r-- | client/src/admin/api/getUser.js | 6 | ||||
-rw-r--r-- | client/src/admin/api/index.js | 4 | ||||
-rw-r--r-- | client/src/admin/api/logout.js | 1 | ||||
-rw-r--r-- | client/src/admin/jsx/App.jsx | 3 | ||||
-rw-r--r-- | client/src/admin/jsx/User.jsx | 2 | ||||
-rw-r--r-- | package-lock.json | 19 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | server/middleware/auth.js | 30 | ||||
-rw-r--r-- | server/models/User.js | 31 | ||||
-rw-r--r-- | server/routes/user.js | 25 |
13 files changed, 144 insertions, 44 deletions
@@ -16,7 +16,13 @@ app.use(cookieParser()); app.use('/api/user/', userRoutes); -app.use('/admin/', auth, express.static(path.join(__dirname, 'client/admin'))); +app.use('/admin/', auth, express.static(path.join(__dirname, 'client/admin'), { + setHeaders: function (res, path, stat) { + if (res.req.newToken){ + res.set('Set-Cookie', "token=" + res.req.newToken + ";httpOnly;MaxAge=604800000;Path=/"); + } + } +})); app.use('/login/', redirectIfLoggedIn, express.static(path.join(__dirname, 'client/login'))); diff --git a/client/admin/out.js b/client/admin/out.js index 93e3b6e..c89fbde 100644 --- a/client/admin/out.js +++ b/client/admin/out.js @@ -86,6 +86,30 @@ /************************************************************************/ /******/ ({ +/***/ "./client/src/admin/api/getUser.js": +/*!*****************************************!*\ + !*** ./client/src/admin/api/getUser.js ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = ((setUser) => (\n fetch('/api/user/me')\n .then(res => res.json())\n .then(data => setUser(data.email))\n .catch(() => {})\n));\n\n\n//# sourceURL=webpack:///./client/src/admin/api/getUser.js?"); + +/***/ }), + +/***/ "./client/src/admin/api/index.js": +/*!***************************************!*\ + !*** ./client/src/admin/api/index.js ***! + \***************************************/ +/*! exports provided: getUser, logout */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _getUser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getUser */ \"./client/src/admin/api/getUser.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"getUser\", function() { return _getUser__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; });\n\n/* harmony import */ var _logout__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./logout */ \"./client/src/admin/api/logout.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"logout\", function() { return _logout__WEBPACK_IMPORTED_MODULE_1__[\"default\"]; });\n\n\n\n\n\n\n\n//# sourceURL=webpack:///./client/src/admin/api/index.js?"); + +/***/ }), + /***/ "./client/src/admin/api/logout.js": /*!****************************************!*\ !*** ./client/src/admin/api/logout.js ***! @@ -94,7 +118,7 @@ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (() => (\n fetch('/api/user/logout', {\n method: 'POST',\n })\n .then(() => window.location.href = \"/\")\n .catch(() => {})\n));\n\n\n//# sourceURL=webpack:///./client/src/admin/api/logout.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (() => (\n fetch('/api/user/logout', {\n method: 'POST',\n })\n .then(() => window.location.href = \"/\")\n .then(() => console.log('it will logout'))\n .catch(() => {})\n));\n\n\n//# sourceURL=webpack:///./client/src/admin/api/logout.js?"); /***/ }), @@ -166,7 +190,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Wit /***/ (function(module, exports, __webpack_require__) { "use strict"; -eval("\n\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _reactDom = __webpack_require__(/*! react-dom */ \"./node_modules/react-dom/index.js\");\n\nvar _reactDom2 = _interopRequireDefault(_reactDom);\n\n__webpack_require__(/*! ../scss/index.scss */ \"./client/src/admin/scss/index.scss\");\n\nvar _TopBar = __webpack_require__(/*! ./TopBar.jsx */ \"./client/src/admin/jsx/TopBar.jsx\");\n\nvar _TopBar2 = _interopRequireDefault(_TopBar);\n\nvar _Info = __webpack_require__(/*! ./Info.jsx */ \"./client/src/admin/jsx/Info.jsx\");\n\nvar _Info2 = _interopRequireDefault(_Info);\n\nvar _MainScreen = __webpack_require__(/*! ./MainScreen.jsx */ \"./client/src/admin/jsx/MainScreen.jsx\");\n\nvar _MainScreen2 = _interopRequireDefault(_MainScreen);\n\nvar _context = __webpack_require__(/*! ../context */ \"./client/src/admin/context/index.js\");\n\nvar _context2 = _interopRequireDefault(_context);\n\nvar _translations = __webpack_require__(/*! ../data/translations */ \"./client/src/admin/data/translations.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar App = function App() {\n var _useState = (0, _react.useState)(_translations.defaultLanguage),\n _useState2 = _slicedToArray(_useState, 2),\n lang = _useState2[0],\n setLang = _useState2[1];\n\n var _useState3 = (0, _react.useState)([]),\n _useState4 = _slicedToArray(_useState3, 2),\n projects = _useState4[0],\n setProjects = _useState4[1];\n\n var _useState5 = (0, _react.useState)(''),\n _useState6 = _slicedToArray(_useState5, 2),\n info = _useState6[0],\n setInfo = _useState6[1];\n\n var _useState7 = (0, _react.useState)(''),\n _useState8 = _slicedToArray(_useState7, 2),\n hover = _useState8[0],\n setHover = _useState8[1];\n\n var _useState9 = (0, _react.useState)('main'),\n _useState10 = _slicedToArray(_useState9, 2),\n view = _useState10[0],\n setView = _useState10[1];\n\n var _useState11 = (0, _react.useState)(null),\n _useState12 = _slicedToArray(_useState11, 2),\n user = _useState12[0],\n setUser = _useState12[1];\n\n (0, _react.useEffect)(function () {\n setInfo('no-saved-websites');\n setUser('admin@op.pl');\n }, []);\n\n return _react2.default.createElement(\n _context2.default.Provider,\n { value: { lang: lang, setHover: setHover, setInfo: setInfo } },\n _react2.default.createElement(\n 'div',\n { className: 'main' },\n _react2.default.createElement(_TopBar2.default, { lang: lang, setLang: setLang, user: user, setUser: setUser }),\n _react2.default.createElement(\n 'div',\n { className: 'main__content' },\n view === 'main' && _react2.default.createElement(_MainScreen2.default, { projects: projects })\n ),\n _react2.default.createElement(_Info2.default, { info: info, hover: hover })\n )\n );\n};\n\n_reactDom2.default.render(_react2.default.createElement(App, null), document.getElementById('app'));\n\n//# sourceURL=webpack:///./client/src/admin/jsx/App.jsx?"); +eval("\n\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _reactDom = __webpack_require__(/*! react-dom */ \"./node_modules/react-dom/index.js\");\n\nvar _reactDom2 = _interopRequireDefault(_reactDom);\n\n__webpack_require__(/*! ../scss/index.scss */ \"./client/src/admin/scss/index.scss\");\n\nvar _TopBar = __webpack_require__(/*! ./TopBar.jsx */ \"./client/src/admin/jsx/TopBar.jsx\");\n\nvar _TopBar2 = _interopRequireDefault(_TopBar);\n\nvar _Info = __webpack_require__(/*! ./Info.jsx */ \"./client/src/admin/jsx/Info.jsx\");\n\nvar _Info2 = _interopRequireDefault(_Info);\n\nvar _MainScreen = __webpack_require__(/*! ./MainScreen.jsx */ \"./client/src/admin/jsx/MainScreen.jsx\");\n\nvar _MainScreen2 = _interopRequireDefault(_MainScreen);\n\nvar _context = __webpack_require__(/*! ../context */ \"./client/src/admin/context/index.js\");\n\nvar _context2 = _interopRequireDefault(_context);\n\nvar _translations = __webpack_require__(/*! ../data/translations */ \"./client/src/admin/data/translations.js\");\n\nvar _api = __webpack_require__(/*! ../api */ \"./client/src/admin/api/index.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar App = function App() {\n var _useState = (0, _react.useState)(_translations.defaultLanguage),\n _useState2 = _slicedToArray(_useState, 2),\n lang = _useState2[0],\n setLang = _useState2[1];\n\n var _useState3 = (0, _react.useState)([]),\n _useState4 = _slicedToArray(_useState3, 2),\n projects = _useState4[0],\n setProjects = _useState4[1];\n\n var _useState5 = (0, _react.useState)(''),\n _useState6 = _slicedToArray(_useState5, 2),\n info = _useState6[0],\n setInfo = _useState6[1];\n\n var _useState7 = (0, _react.useState)(''),\n _useState8 = _slicedToArray(_useState7, 2),\n hover = _useState8[0],\n setHover = _useState8[1];\n\n var _useState9 = (0, _react.useState)('main'),\n _useState10 = _slicedToArray(_useState9, 2),\n view = _useState10[0],\n setView = _useState10[1];\n\n var _useState11 = (0, _react.useState)(null),\n _useState12 = _slicedToArray(_useState11, 2),\n user = _useState12[0],\n setUser = _useState12[1];\n\n (0, _react.useEffect)(function () {\n (0, _api.getUser)(setUser);\n setInfo('no-saved-websites');\n }, []);\n\n return _react2.default.createElement(\n _context2.default.Provider,\n { value: { lang: lang, setHover: setHover, setInfo: setInfo } },\n _react2.default.createElement(\n 'div',\n { className: 'main' },\n _react2.default.createElement(_TopBar2.default, { lang: lang, setLang: setLang, user: user, setUser: setUser }),\n _react2.default.createElement(\n 'div',\n { className: 'main__content' },\n view === 'main' && _react2.default.createElement(_MainScreen2.default, { projects: projects })\n ),\n _react2.default.createElement(_Info2.default, { info: info, hover: hover })\n )\n );\n};\n\n_reactDom2.default.render(_react2.default.createElement(App, null), document.getElementById('app'));\n\n//# sourceURL=webpack:///./client/src/admin/jsx/App.jsx?"); /***/ }), @@ -226,7 +250,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n /***/ (function(module, exports, __webpack_require__) { "use strict"; -eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _hocs = __webpack_require__(/*! ../hocs */ \"./client/src/admin/hocs/index.js\");\n\nvar _logout = __webpack_require__(/*! ../api/logout */ \"./client/src/admin/api/logout.js\");\n\nvar _logout2 = _interopRequireDefault(_logout);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar User = function User(_ref) {\n var user = _ref.user,\n setUser = _ref.setUser,\n opened = _ref.opened,\n setOpened = _ref.setOpened;\n\n var handleLogout = function handleLogout() {\n setOpened(false);\n (0, _logout2.default)();\n };\n var handleChangePass = function handleChangePass() {\n setOpened(false);\n };\n var handleRemoveUser = function handleRemoveUser() {\n setOpened(false);\n };\n\n return _react2.default.createElement(\n 'div',\n { className: 'user' },\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-change-user' },\n _react2.default.createElement(\n 'span',\n {\n className: 'user__main-item' + (opened === 'user' ? ' user__main-item--active' : ''),\n onClick: function onClick() {\n return setOpened(opened !== 'user' ? 'user' : false);\n }\n },\n user\n ),\n opened === 'user' && _react2.default.createElement(\n 'div',\n { className: 'user__list' },\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-logout' },\n _react2.default.createElement(\n 'span',\n { className: 'user__item', onClick: handleLogout },\n (0, _hocs.t)('logout')\n )\n ),\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-change-user-settings' },\n _react2.default.createElement(\n 'span',\n { className: 'user__item', onClick: handleChangePass },\n (0, _hocs.t)('user-settings')\n )\n )\n )\n )\n );\n};\n\nexports.default = User;\n\n//# sourceURL=webpack:///./client/src/admin/jsx/User.jsx?"); +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _hocs = __webpack_require__(/*! ../hocs */ \"./client/src/admin/hocs/index.js\");\n\nvar _api = __webpack_require__(/*! ../api */ \"./client/src/admin/api/index.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar User = function User(_ref) {\n var user = _ref.user,\n setUser = _ref.setUser,\n opened = _ref.opened,\n setOpened = _ref.setOpened;\n\n var handleLogout = function handleLogout() {\n setOpened(false);\n (0, _api.logout)();\n };\n var handleChangePass = function handleChangePass() {\n setOpened(false);\n };\n var handleRemoveUser = function handleRemoveUser() {\n setOpened(false);\n };\n\n return _react2.default.createElement(\n 'div',\n { className: 'user' },\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-change-user' },\n _react2.default.createElement(\n 'span',\n {\n className: 'user__main-item' + (opened === 'user' ? ' user__main-item--active' : ''),\n onClick: function onClick() {\n return setOpened(opened !== 'user' ? 'user' : false);\n }\n },\n user\n ),\n opened === 'user' && _react2.default.createElement(\n 'div',\n { className: 'user__list' },\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-logout' },\n _react2.default.createElement(\n 'span',\n { className: 'user__item', onClick: handleLogout },\n (0, _hocs.t)('logout')\n )\n ),\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-change-user-settings' },\n _react2.default.createElement(\n 'span',\n { className: 'user__item', onClick: handleChangePass },\n (0, _hocs.t)('user-settings')\n )\n )\n )\n )\n );\n};\n\nexports.default = User;\n\n//# sourceURL=webpack:///./client/src/admin/jsx/User.jsx?"); /***/ }), diff --git a/client/login/out.js b/client/login/out.js index 0381910..b2651d2 100644 --- a/client/login/out.js +++ b/client/login/out.js @@ -86,6 +86,30 @@ /************************************************************************/ /******/ ({ +/***/ "./client/src/admin/api/getUser.js": +/*!*****************************************!*\ + !*** ./client/src/admin/api/getUser.js ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = ((setUser) => (\n fetch('/api/user/me')\n .then(res => res.json())\n .then(data => setUser(data.email))\n .catch(() => {})\n));\n\n\n//# sourceURL=webpack:///./client/src/admin/api/getUser.js?"); + +/***/ }), + +/***/ "./client/src/admin/api/index.js": +/*!***************************************!*\ + !*** ./client/src/admin/api/index.js ***! + \***************************************/ +/*! exports provided: getUser, logout */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _getUser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getUser */ \"./client/src/admin/api/getUser.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"getUser\", function() { return _getUser__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; });\n\n/* harmony import */ var _logout__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./logout */ \"./client/src/admin/api/logout.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"logout\", function() { return _logout__WEBPACK_IMPORTED_MODULE_1__[\"default\"]; });\n\n\n\n\n\n\n\n//# sourceURL=webpack:///./client/src/admin/api/index.js?"); + +/***/ }), + /***/ "./client/src/admin/api/logout.js": /*!****************************************!*\ !*** ./client/src/admin/api/logout.js ***! @@ -94,7 +118,7 @@ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (() => (\n fetch('/api/user/logout', {\n method: 'POST',\n })\n .then(() => window.location.href = \"/\")\n .catch(() => {})\n));\n\n\n//# sourceURL=webpack:///./client/src/admin/api/logout.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (() => (\n fetch('/api/user/logout', {\n method: 'POST',\n })\n .then(() => window.location.href = \"/\")\n .then(() => console.log('it will logout'))\n .catch(() => {})\n));\n\n\n//# sourceURL=webpack:///./client/src/admin/api/logout.js?"); /***/ }), @@ -202,7 +226,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n /***/ (function(module, exports, __webpack_require__) { "use strict"; -eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _hocs = __webpack_require__(/*! ../hocs */ \"./client/src/admin/hocs/index.js\");\n\nvar _logout = __webpack_require__(/*! ../api/logout */ \"./client/src/admin/api/logout.js\");\n\nvar _logout2 = _interopRequireDefault(_logout);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar User = function User(_ref) {\n var user = _ref.user,\n setUser = _ref.setUser,\n opened = _ref.opened,\n setOpened = _ref.setOpened;\n\n var handleLogout = function handleLogout() {\n setOpened(false);\n (0, _logout2.default)();\n };\n var handleChangePass = function handleChangePass() {\n setOpened(false);\n };\n var handleRemoveUser = function handleRemoveUser() {\n setOpened(false);\n };\n\n return _react2.default.createElement(\n 'div',\n { className: 'user' },\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-change-user' },\n _react2.default.createElement(\n 'span',\n {\n className: 'user__main-item' + (opened === 'user' ? ' user__main-item--active' : ''),\n onClick: function onClick() {\n return setOpened(opened !== 'user' ? 'user' : false);\n }\n },\n user\n ),\n opened === 'user' && _react2.default.createElement(\n 'div',\n { className: 'user__list' },\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-logout' },\n _react2.default.createElement(\n 'span',\n { className: 'user__item', onClick: handleLogout },\n (0, _hocs.t)('logout')\n )\n ),\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-change-user-settings' },\n _react2.default.createElement(\n 'span',\n { className: 'user__item', onClick: handleChangePass },\n (0, _hocs.t)('user-settings')\n )\n )\n )\n )\n );\n};\n\nexports.default = User;\n\n//# sourceURL=webpack:///./client/src/admin/jsx/User.jsx?"); +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _hocs = __webpack_require__(/*! ../hocs */ \"./client/src/admin/hocs/index.js\");\n\nvar _api = __webpack_require__(/*! ../api */ \"./client/src/admin/api/index.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar User = function User(_ref) {\n var user = _ref.user,\n setUser = _ref.setUser,\n opened = _ref.opened,\n setOpened = _ref.setOpened;\n\n var handleLogout = function handleLogout() {\n setOpened(false);\n (0, _api.logout)();\n };\n var handleChangePass = function handleChangePass() {\n setOpened(false);\n };\n var handleRemoveUser = function handleRemoveUser() {\n setOpened(false);\n };\n\n return _react2.default.createElement(\n 'div',\n { className: 'user' },\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-change-user' },\n _react2.default.createElement(\n 'span',\n {\n className: 'user__main-item' + (opened === 'user' ? ' user__main-item--active' : ''),\n onClick: function onClick() {\n return setOpened(opened !== 'user' ? 'user' : false);\n }\n },\n user\n ),\n opened === 'user' && _react2.default.createElement(\n 'div',\n { className: 'user__list' },\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-logout' },\n _react2.default.createElement(\n 'span',\n { className: 'user__item', onClick: handleLogout },\n (0, _hocs.t)('logout')\n )\n ),\n _react2.default.createElement(\n _hocs.WithHover,\n { message: 'click-to-change-user-settings' },\n _react2.default.createElement(\n 'span',\n { className: 'user__item', onClick: handleChangePass },\n (0, _hocs.t)('user-settings')\n )\n )\n )\n )\n );\n};\n\nexports.default = User;\n\n//# sourceURL=webpack:///./client/src/admin/jsx/User.jsx?"); /***/ }), diff --git a/client/src/admin/api/getUser.js b/client/src/admin/api/getUser.js new file mode 100644 index 0000000..930ed3b --- /dev/null +++ b/client/src/admin/api/getUser.js @@ -0,0 +1,6 @@ +export default (setUser) => ( + fetch('/api/user/me') + .then(res => res.json()) + .then(data => setUser(data.email)) + .catch(() => {}) +); diff --git a/client/src/admin/api/index.js b/client/src/admin/api/index.js new file mode 100644 index 0000000..5b4f9dc --- /dev/null +++ b/client/src/admin/api/index.js @@ -0,0 +1,4 @@ +import getUser from './getUser'; +import logout from './logout'; + +export { getUser, logout }; diff --git a/client/src/admin/api/logout.js b/client/src/admin/api/logout.js index b0a9841..76137da 100644 --- a/client/src/admin/api/logout.js +++ b/client/src/admin/api/logout.js @@ -3,5 +3,6 @@ export default () => ( method: 'POST', }) .then(() => window.location.href = "/") + .then(() => console.log('it will logout')) .catch(() => {}) ); diff --git a/client/src/admin/jsx/App.jsx b/client/src/admin/jsx/App.jsx index 146af70..93b6a33 100644 --- a/client/src/admin/jsx/App.jsx +++ b/client/src/admin/jsx/App.jsx @@ -8,6 +8,7 @@ import Info from './Info.jsx'; import MainScreen from './MainScreen.jsx'; import Context from '../context'; import { defaultLanguage } from '../data/translations'; +import { getUser } from '../api'; const App = () => { const [lang, setLang] = useState(defaultLanguage); @@ -18,8 +19,8 @@ const App = () => { const [user, setUser] = useState(null); useEffect(() => { + getUser(setUser); setInfo('no-saved-websites'); - setUser('admin@op.pl'); }, []); return ( diff --git a/client/src/admin/jsx/User.jsx b/client/src/admin/jsx/User.jsx index 22b96b4..131251e 100644 --- a/client/src/admin/jsx/User.jsx +++ b/client/src/admin/jsx/User.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { WithHover, t } from '../hocs'; -import logout from '../api/logout'; +import { logout } from '../api'; const User = ({ user, setUser, opened, setOpened }) => { const handleLogout = () => { diff --git a/package-lock.json b/package-lock.json index 1f818ce..8dbe3b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "3-minute-website", + "name": "website-creator", "version": "1.0.0", "lockfileVersion": 1, "requires": true, @@ -2520,15 +2520,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, "create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -5493,7 +5484,8 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true }, "object-copy": { "version": "0.1.0", @@ -6047,6 +6039,11 @@ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, + "rand-token": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rand-token/-/rand-token-1.0.1.tgz", + "integrity": "sha512-Zri5SfJmEzBJ3IexFdigvPSCamslJ7UjLkUn0tlgH7COJvaUr5V7FyUYgKifEMTw7gFO8ZLcWjcU+kq8akipzg==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", diff --git a/package.json b/package.json index df93bc0..263bbc7 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "jsonwebtoken": "^8.5.1", "mongoose": "^5.10.13", "npm-run-all": "^4.1.5", + "rand-token": "^1.0.1", "request": "^2.88.0" }, "devDependencies": { diff --git a/server/middleware/auth.js b/server/middleware/auth.js index 42d93a4..462b100 100644 --- a/server/middleware/auth.js +++ b/server/middleware/auth.js @@ -9,16 +9,32 @@ const auth = async (req, res, next) => { throw new Error(); } - const decoded = jwt.verify(token, 'replaceThisWithSecretString'); - const user = await User.findOne({ _id: decoded._id, 'tokens.token': token }); + try { + const decoded = jwt.verify(token, 'replaceThisWithSecretString'); + req.userId = decoded._id; + req.refreshToken = decoded.ref; + return next(); + } catch(er) { + if (er.message && er.message === 'jwt expired') { + const { _id, ref } = jwt.decode(token, 'replaceThisWithSecretString'); + const user = await User.findById(_id); + + if (!user) { + throw new Error(); + } + + if (user.sessions.filter(s => s.ref === ref).length > 0) { + req.userId = _id; + req.refreshToken = ref; + req.newToken = await user.generateJwtToken(res.req.refreshToken);; + return next(); + } + + throw new Error(); + } - if (!user) { throw new Error(); } - - req.token = token; - req.user = user; - next(); } catch (err) { res.redirect('/login'); } diff --git a/server/models/User.js b/server/models/User.js index 4fa6ffe..e777878 100644 --- a/server/models/User.js +++ b/server/models/User.js @@ -1,5 +1,6 @@ const mongoose = require("mongoose"); const bcrypt = require('bcryptjs'); +const randtoken = require('rand-token'); const jwt = require('jsonwebtoken'); const userSchema = new mongoose.Schema({ @@ -23,22 +24,36 @@ const userSchema = new mongoose.Schema({ min: 4, max: 1024, }, - tokens: [{ - token: { + sessions: [{ + ref: { type: String, required: true } }] }); -userSchema.methods.generateAuthToken = async function () { - const user = this; - const token = jwt.sign({ _id: user._id.toString() }, 'replaceThisWithSecretString') +userSchema.methods.generateJwtToken = async function (currentRef) { + const ref = currentRef ? currentRef : randtoken.uid(256); + + if (!currentRef) { + this.sessions = this.sessions.concat({ ref }); + this.save(); + } + + return jwt.sign( + { _id: this._id.toString(), ref }, + 'replaceThisWithSecretString', + { expiresIn: 300 } + ); +} - user.tokens = user.tokens.concat({ token }); - user.save(); +userSchema.methods.endSession = async function (ref) { + this.sessions = this.sessions.filter((session) => { + return session.ref !== ref; + }); - return token; + await this.save(); + return null; } userSchema.statics.findByCredentials = async (email, password) => { diff --git a/server/routes/user.js b/server/routes/user.js index d1100bc..b3bdee3 100644 --- a/server/routes/user.js +++ b/server/routes/user.js @@ -1,14 +1,19 @@ const router = require('express').Router(); const User = require('../models/User'); const auth = require('../middleware/auth'); +const jwt = require('jsonwebtoken'); + +router.get('/me', auth, async (req, res) => { + const user = await User.findById(req.userId); + res.json({ email: user.email }); +}) router.post('/register', async (req, res) => { const user = new User(req.body); try { await user.save(); - const token = await user.generateAuthToken(); - res.status(201).send({ user, token }); + res.status(201).send({ email: user.email }); } catch(err) { if (err._message) { res.status(422).send(err._message); @@ -23,10 +28,10 @@ router.post('/register', async (req, res) => { router.post('/login', async (req, res) => { try { const user = await User.findByCredentials(req.body.email, req.body.password); - const token = await user.generateAuthToken(); + const token = await user.generateJwtToken(); res .cookie('token', token, { - expires: new Date(Date.now() + 604800000), + maxAge: 604800000, secure: false, httpOnly: true, }) @@ -39,12 +44,12 @@ router.post('/login', async (req, res) => { router.post('/logout', auth, async (req, res) => { try { - req.user.tokens = req.user.tokens.filter((token) => { - return token.token !== req.token; - }); - await req.user.save(); - - res.status(204).send(); + const user = await User.findById(req.userId); + await user.endSession(req.refreshToken); + res + .clearCookie('token') + .status(204) + .send(); } catch (err) { res.status(500).send(); } |