diff --git a/application/models.py b/application/models.py index 9aff69c..9a9138b 100644 --- a/application/models.py +++ b/application/models.py @@ -13,8 +13,8 @@ def __init__(self, email, password): @staticmethod def hashed_password(password): - return bcrypt.generate_password_hash(password).decode("utf-8") - + return bcrypt.generate_password_hash(password) + @staticmethod def get_user_with_email_and_password(email, password): user = User.query.filter_by(email=email).first() diff --git a/static/.babelrc b/static/.babelrc index 535d3c8..e88f7ae 100755 --- a/static/.babelrc +++ b/static/.babelrc @@ -1,11 +1,6 @@ { - "presets": ["react", "es2015" , "stage-0"], + "presets": ["@babel/react"], "plugins": [ - ["transform-decorators-legacy"] - ], - "env": { - "start": { - "presets": ["react-hmre"] - } - } + ["@babel/plugin-proposal-decorators", { "legacy": true }] + ] } diff --git a/static/bin/server.js b/static/bin/server.js index ceb6ad4..6f91b02 100755 --- a/static/bin/server.js +++ b/static/bin/server.js @@ -10,5 +10,5 @@ try { console.error(err); } -require('babel-core/register')(config); +require("@babel/register")(config); require('../server'); diff --git a/static/package.json b/static/package.json index 37808c3..ce46c5e 100644 --- a/static/package.json +++ b/static/package.json @@ -29,92 +29,93 @@ "author": "https://github.com/anorudes, https://github.com/keske", "license": "MIT", "devDependencies": { - "autoprefixer": "6.5.3", - "axios": "^0.15.3", - "babel-core": "^6.4.5", + "autoprefixer": "10.3.0", + "axios": "^0.21.1", "babel-eslint": "^7.1.1", - "babel-loader": "^6.2.1", - "babel-plugin-react-transform": "^2.0.0", - "babel-plugin-transform-decorators-legacy": "^1.3.4", - "babel-polyfill": "^6.3.14", + "babel-loader": "^8.2.2", + "babel-plugin-react-transform": "^3.0.0", + "babel-polyfill": "^6.26.0", "babel-preset-es2015": "^6.3.13", - "babel-preset-react": "^6.3.13", - "babel-preset-react-hmre": "^1.0.1", - "babel-preset-stage-0": "^6.3.13", - "bootstrap": "^3.3.5", - "bootstrap-loader": "^1.2.0-beta.1", - "bootstrap-sass": "^3.3.6", - "bootstrap-webpack": "0.0.5", - "classnames": "^2.2.3", - "css-loader": "^0.26.1", + "bootstrap": "^5.0.2", + "bootstrap-loader": "^3.0.4", + "bootstrap-sass": "^3.4.1", + "bootstrap-webpack": "0.0.6", + "classnames": "^2.3.1", + "css-loader": "^5.2.6", "csswring": "^5.1.0", - "deep-equal": "^1.0.1", - "eslint": "^3.4.0", - "eslint-config-airbnb": "13.0.0", - "eslint-plugin-import": "^2.2.0", - "eslint-plugin-jsx-a11y": "^3.0.1", - "eslint-plugin-react": "^6.1.2", - "expect": "^1.13.4", - "exports-loader": "^0.6.2", - "expose-loader": "^0.7.1", - "express": "^4.13.4", - "express-open-in-editor": "^1.1.0", - "extract-text-webpack-plugin": "^1.0.1", - "file-loader": "^0.9.0", + "deep-equal": "^2.0.5", + "eslint": "^7.30.0", + "eslint-config-airbnb": "18.2.1", + "eslint-plugin-import": "^2.23.4", + "eslint-plugin-jsx-a11y": "^6.4.1", + "eslint-plugin-react": "^7.24.0", + "expect": "^27.0.6", + "exports-loader": "^3.0.0", + "expose-loader": "^3.0.0", + "express": "^4.17.1", + "express-open-in-editor": "^3.1.1", + "file-loader": "^6.2.0", "gapi": "0.0.3", - "history": "^4.4.1", - "http-proxy": "^1.12.0", - "imports-loader": "^0.6.5", - "jasmine-core": "^2.4.1", - "jquery": "^3.1.0", - "jwt-decode": "^2.1.0", - "karma": "^1.2.0", - "karma-chrome-launcher": "^2.0.0", - "karma-mocha": "^1.1.1", - "karma-webpack": "^1.7.0", - "less": "^2.5.3", - "less-loader": "^2.2.2", - "lodash": "^4.5.1", - "material-ui": "^0.16.4", - "mocha": "^3.0.2", - "morgan": "^1.6.1", - "node-sass": "^3.4.2", - "postcss-import": "^9.0.0", - "postcss-loader": "^1.1.1", - "q": "^1.4.1", - "qs": "^6.1.0", - "rc-datepicker": "^4.0.1", - "react": "^15.3.1", - "react-addons-css-transition-group": "^15.3.1", - "react-calendar-component": "^1.0.0", - "react-date-picker": "^5.3.28", - "react-datepicker": "^0.37.0", - "react-document-meta": "^2.0.0-rc2", - "react-dom": "^15.1.0", + "history": "^4.10.1", + "http-proxy": "^1.18.1", + "imports-loader": "^3.0.0", + "jasmine-core": "^3.8.0", + "jquery": "^3.6.0", + "jwt-decode": "^3.1.2", + "karma": "^6.3.4", + "karma-chrome-launcher": "^3.1.0", + "karma-mocha": "^2.0.1", + "karma-webpack": "^5.0.0", + "less": "^4.1.1", + "less-loader": "^10.0.1", + "lodash": "^4.17.21", + "material-ui": "^0.20.0", + "mocha": "^9.0.2", + "morgan": "^1.10.0", + "node-sass": "^6.0.1", + "postcss-import": "^14.0.2", + "postcss-loader": "^6.1.1", + "q": "^1.5.1", + "qs": "^6.10.1", + "rc-datepicker": "^5.0.16", + "react": "^17.0.2", + "react-addons-css-transition-group": "^15.6.2", + "react-calendar-component": "^3.0.0", + "react-date-picker": "^8.2.0", + "react-datepicker": "^4.1.1", + "react-document-meta": "^3.0.0-beta.2", + "react-dom": "^17.0.2", "react-forms": "^2.0.0-beta33", - "react-hot-loader": "^1.3.0", + "react-hot-loader": "^4.13.0", "react-loading-order-with-animation": "^1.0.0", - "react-onclickoutside": "^5.3.3", - "react-redux": "^4.3.0", - "react-router": "3.0.0", - "react-router-redux": "^4.0.0", - "react-tap-event-plugin": "^2.0.1", - "react-transform-hmr": "^1.0.1", - "redux": "^3.2.1", - "redux-form": "^6.0.1", - "redux-logger": "2.7.4", - "redux-thunk": "^2.1.0", - "resolve-url-loader": "^1.4.3", - "rimraf": "^2.5.0", - "sass-loader": "^4.0.0", - "style-loader": "^0.13.0", - "url-loader": "^0.5.7", - "webpack": "^1.12.11", - "webpack-dev-middleware": "^1.5.0", - "webpack-dev-server": "^1.14.1", - "webpack-hot-middleware": "^2.6.0", - "webpack-merge": "^1.0.2", - "yargs": "^6.5.0" + "react-onclickoutside": "^6.11.2", + "react-redux": "^7.2.4", + "react-router": "5.2.0", + "react-router-redux": "^4.0.8", + "react-tap-event-plugin": "^3.0.3", + "react-transform-hmr": "^1.0.4", + "redux": "^4.1.0", + "redux-form": "^8.3.7", + "redux-logger": "3.0.6", + "redux-thunk": "^2.3.0", + "resolve-url-loader": "^4.0.0", + "rimraf": "^3.0.2", + "sass-loader": "^12.1.0", + "style-loader": "^3.0.0", + "url-loader": "^4.1.1", + "webpack": "^5.44.0", + "webpack-dev-middleware": "^5.0.0", + "webpack-dev-server": "^3.11.2", + "webpack-hot-middleware": "^2.25.0", + "webpack-merge": "^5.8.0", + "yargs": "^17.0.1" }, - "dependencies": {} + "dependencies": { + "@babel/core": "^7.14.6", + "@babel/plugin-proposal-decorators": "^7.14.5", + "@babel/register": "^7.14.5", + "duplicate-package-checker-webpack-plugin": "^3.0.0", + "mini-css-extract-plugin": "^2.1.0", + "uglifyjs-webpack-plugin": "^2.2.0" + } } diff --git a/static/server.js b/static/server.js index 8a2c2d1..cb23d7c 100755 --- a/static/server.js +++ b/static/server.js @@ -16,7 +16,7 @@ app.use(require('morgan')('short')); const compiler = webpack(webpackConfig); app.use(require('webpack-dev-middleware')(compiler, { - noInfo: true, publicPath: webpackConfig.output.publicPath, + publicPath: webpackConfig.output.publicPath, })); app.use(require('webpack-hot-middleware')(compiler, { diff --git a/static/src/actions/auth.js b/static/src/actions/auth.js index a992dc9..b858817 100644 --- a/static/src/actions/auth.js +++ b/static/src/actions/auth.js @@ -1,5 +1,3 @@ -import { browserHistory } from 'react-router'; - import { LOGIN_USER_SUCCESS, LOGIN_USER_FAILURE, @@ -8,11 +6,22 @@ import { REGISTER_USER_FAILURE, REGISTER_USER_REQUEST, REGISTER_USER_SUCCESS, + SET_AUTH, } from '../constants/index'; import { parseJSON } from '../utils/misc'; import { get_token, create_user } from '../utils/http_functions'; +export function setAuth(data) { + return { + type: SET_AUTH, + payload: { + data: data, + }, + }; +} + + export function loginUserSuccess(token) { localStorage.setItem('token', token); @@ -49,20 +58,20 @@ export function logout() { }; } -export function logoutAndRedirect() { +export function logoutAndRedirect(history) { return (dispatch) => { dispatch(logout()); - browserHistory.push('/'); + history.push('/'); }; } -export function redirectToRoute(route) { +export function redirectToRoute(route, history) { return () => { - browserHistory.push(route); + history.push(route); }; } -export function loginUser(email, password) { +export function loginUser(email, password, history) { return function (dispatch) { dispatch(loginUserRequest()); return get_token(email, password) @@ -70,7 +79,7 @@ export function loginUser(email, password) { .then(response => { try { dispatch(loginUserSuccess(response.token)); - browserHistory.push('/main'); + history.push('/main'); } catch (e) { alert(e); dispatch(loginUserFailure({ @@ -120,7 +129,7 @@ export function registerUserFailure(error) { }; } -export function registerUser(email, password) { +export function registerUser(email, password, history) { return function (dispatch) { dispatch(registerUserRequest()); return create_user(email, password) @@ -128,7 +137,7 @@ export function registerUser(email, password) { .then(response => { try { dispatch(registerUserSuccess(response.token)); - browserHistory.push('/main'); + history.push('/main'); } catch (e) { dispatch(registerUserFailure({ response: { diff --git a/static/src/actions/data.js b/static/src/actions/data.js index 0c4f7e1..b3ef7b9 100644 --- a/static/src/actions/data.js +++ b/static/src/actions/data.js @@ -18,18 +18,16 @@ export function fetchProtectedDataRequest() { }; } -export function fetchProtectedData(token) { - return (dispatch) => { - dispatch(fetchProtectedDataRequest()); - data_about_user(token) - .then(parseJSON) - .then(response => { - dispatch(receiveProtectedData(response.result)); - }) - .catch(error => { - if (error.status === 401) { - dispatch(logoutAndRedirect(error)); - } - }); - }; +export function fetchProtectedData(token, dispatch) { + dispatch(fetchProtectedDataRequest()); + data_about_user(token) + .then(parseJSON) + .then(response => { + dispatch(receiveProtectedData(response.result)); + }) + .catch(error => { + if (error.status === 401) { + dispatch(logoutAndRedirect(error)); + } + }); } diff --git a/static/src/actions/option.js b/static/src/actions/option.js new file mode 100644 index 0000000..0b8ec6e --- /dev/null +++ b/static/src/actions/option.js @@ -0,0 +1,21 @@ +import { SET_LOAD_IF_NEEDED, SET_SIDEBAR_OPEN } from "../constants"; + + +export function setLoadIfNeeded(value) { + return { + type: SET_LOAD_IF_NEEDED, + payload: { + data: value, + }, + }; +} + + +export function setSideBarOpen(value) { + return { + type: SET_SIDEBAR_OPEN, + payload: { + data: value, + }, + }; +} \ No newline at end of file diff --git a/static/src/actions/register.js b/static/src/actions/register.js new file mode 100644 index 0000000..bc0bcfd --- /dev/null +++ b/static/src/actions/register.js @@ -0,0 +1,12 @@ +import { SET_REGISTER } from "../constants"; + + +export function setRegister(data) { + return { + type: SET_REGISTER, + payload: { + data: data, + }, + }; +} + diff --git a/static/src/components/AuthenticatedComponent.js b/static/src/components/AuthenticatedComponent.js index 66cd2d4..b8157bb 100755 --- a/static/src/components/AuthenticatedComponent.js +++ b/static/src/components/AuthenticatedComponent.js @@ -1,40 +1,23 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import { browserHistory } from 'react-router'; -import * as actionCreators from '../actions/auth'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router'; +import { useComponentDidMount } from '../utils/lifecycle_hook'; +import * as authActions from '../actions/auth'; +import * as optionActions from '../actions/option'; -function mapStateToProps(state) { - return { - token: state.auth.token, - userName: state.auth.userName, - isAuthenticated: state.auth.isAuthenticated, - }; -} - -function mapDispatchToProps(dispatch) { - return bindActionCreators(actionCreators, dispatch); -} - - -export function requireAuthentication(Component) { - class AuthenticatedComponent extends React.Component { - componentWillMount() { - this.checkAuth(); - this.state = { - loaded_if_needed: false, - }; - } - - componentWillReceiveProps(nextProps) { - this.checkAuth(nextProps); - } +export const requireAuthentication = (Component) => { + + const ret = (props) => { + const isAuthenticated = useSelector(state => state.auth.isAuthenticated); + const loadIfNeeded = useSelector(state => state.option.loadIfNeeded); + const dispatch = useDispatch(); + const history = useHistory(); - checkAuth(props = this.props) { - if (!props.isAuthenticated) { + useComponentDidMount(() => { + if (!isAuthenticated) { const token = localStorage.getItem('token'); if (!token) { - browserHistory.push('/home'); + history.push('/home'); } else { fetch('/api/is_token_valid', { method: 'post', @@ -45,44 +28,38 @@ export function requireAuthentication(Component) { }, body: JSON.stringify({ token }), }) - .then(res => { - if (res.status === 200) { - this.props.loginUserSuccess(token); - this.setState({ - loaded_if_needed: true, - }); - - } else { - browserHistory.push('/home'); - - } - }); - + .then(res => { + if (res.status === 200) { + dispatch(authActions.loginUserSuccess(token)); + dispatch(optionActions.setLoadIfNeeded(true)); + } else { + history.push('/home'); + } + }); + } } else { - this.setState({ - loaded_if_needed: true, - }); + dispatch(optionActions.setLoadIfNeeded(true)); } - } + }) - render() { - return ( -