summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Piotr Russ <mail@pruss.it> 2020-11-22 13:49:09 +0100
committerGravatar Piotr Russ <mail@pruss.it> 2020-11-22 13:49:09 +0100
commit4569b85489e863465395f84e995dd3fdc44471b4 (patch)
tree6e4d27883809c94c8b3f3b87159d85c7f3874bbd
parent81ddf9b700bc48a1f8e472209f080f9c1d9a9b09 (diff)
downloadwebsite_creator-4569b85489e863465395f84e995dd3fdc44471b4.tar.gz
website_creator-4569b85489e863465395f84e995dd3fdc44471b4.tar.bz2
website_creator-4569b85489e863465395f84e995dd3fdc44471b4.zip
implement refresh tokens
-rwxr-xr-xapp.js8
-rw-r--r--client/admin/out.js30
-rw-r--r--client/login/out.js28
-rw-r--r--client/src/admin/api/getUser.js6
-rw-r--r--client/src/admin/api/index.js4
-rw-r--r--client/src/admin/api/logout.js1
-rw-r--r--client/src/admin/jsx/App.jsx3
-rw-r--r--client/src/admin/jsx/User.jsx2
-rw-r--r--package-lock.json19
-rw-r--r--package.json1
-rw-r--r--server/middleware/auth.js30
-rw-r--r--server/models/User.js31
-rw-r--r--server/routes/user.js25
13 files changed, 144 insertions, 44 deletions
diff --git a/app.js b/app.js
index 8621cca..40fc07d 100755
--- a/app.js
+++ b/app.js
@@ -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();
}