From 84c5fe0a6cb4187d412906f855563d2ee5122f07 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Sun, 9 Sep 2018 23:11:27 +0200 Subject: [PATCH] Persistent session --- package-lock.json | 76 +++++++++++++++++++ package.json | 3 +- src/Api.js | 6 ++ src/App.js | 2 + src/Categories.js | 84 +++++++++++---------- src/Category.js | 112 ++++++++++++++------------- src/Header.js | 90 ++++++++-------------- src/Login.js | 11 ++- src/Logout.js | 23 ++++++ src/Navigation.js | 77 +++++++++++++++++++ src/Vegetable.js | 188 +++++++++++++++++++++++----------------------- src/index.js | 9 +++ 12 files changed, 432 insertions(+), 249 deletions(-) create mode 100644 src/Logout.js create mode 100644 src/Navigation.js diff --git a/package-lock.json b/package-lock.json index c148fdc..e30b626 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,41 @@ } } }, + "@types/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha512-64Uv+8bTRVZHlbB8eXQgMP9HguxPgnOOIYrQpwHWrtLDrtcG/lILKhUl7bV65NSOIJ9dXGYD7skQFXzhL8tk1A==" + }, + "@types/hoist-non-react-statics": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.0.1.tgz", + "integrity": "sha512-3wTz66vV+WatOAjMST+hKCmo01KYPFgnsu+QeLcn0FuwPCoymX6aj1a4RvFCdVsfh2m0hfTPhE/zTv4M28ho1Q==", + "requires": { + "@types/react": "*" + } + }, + "@types/object-assign": { + "version": "4.0.30", + "resolved": "https://registry.npmjs.org/@types/object-assign/-/object-assign-4.0.30.tgz", + "integrity": "sha1-iUk3HVqZ9Dge4PHfCpt6GH4H5lI=" + }, + "@types/prop-types": { + "version": "15.5.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.5.5.tgz", + "integrity": "sha512-mOrlCEdwX3seT3n0AXNt4KNPAZZxcsABUHwBgFXOt+nvFUXkxCAO6UBJHPrDxWEa2KDMil86355fjo8jbZ+K0Q==", + "requires": { + "@types/react": "*" + } + }, + "@types/react": { + "version": "16.4.13", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.13.tgz", + "integrity": "sha512-a2Z7UmwnAzZ23bTHV6on141S8vvSC7MEJGG85R5/VG80ybzkt5QJqNzlaJ0Y6OX1dncrXFW8B0vWPIx7QuOUqA==", + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -2669,6 +2704,11 @@ "cssom": "0.3.x" } }, + "csstype": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.6.tgz", + "integrity": "sha512-tKPyhy0FmfYD2KQYXD5GzkvAYLYj96cMLXr648CKGd3wBe0QqoPipImjGiLze9c8leJK8J3n7ap90tpk3E6HGQ==" + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -8639,6 +8679,26 @@ "schedule": "^0.3.0" } }, + "react-cookie": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-3.0.4.tgz", + "integrity": "sha512-WNf1LifcjRQfg/QEDYQkey78XNJ46/k+lhoKrTK1Iv1jiqInl5jmjRBnEqDJ32HhgeL0iJAsJrEC+o+LkJ/O9Q==", + "requires": { + "@types/hoist-non-react-statics": "^3.0.1", + "hoist-non-react-statics": "^3.0.0", + "universal-cookie": "^3.0.4" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.0.1.tgz", + "integrity": "sha512-1kXwPsOi0OGQIZNVMPvgWJ9tSnGMiMfJdihqEzrPEXlHOBh9AAHXX/QYmAJTXztnz/K+PQ8ryCb4eGaN6HlGbQ==", + "requires": { + "react-is": "^16.3.2" + } + } + } + }, "react-dev-utils": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-5.0.2.tgz", @@ -8685,6 +8745,11 @@ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-3.0.5.tgz", "integrity": "sha512-gNOTMhB3QCFsDnBkO0psdcz84BjprjT95pX6SSJ9pNARQozTsBqOKeVl+uw8zMIBGGDX9GpdY9TflnRjiX4z1A==" }, + "react-is": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.5.0.tgz", + "integrity": "sha512-kpkCGLsChXTEQJVmowQqHpCjHKJFwB4SIChYaaaiAkq8OtE2aBg5pQe8/xnFlGmz9KmMx1H4oQRUyxP7qC9v5A==" + }, "react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -10599,6 +10664,17 @@ "crypto-random-string": "^1.0.0" } }, + "universal-cookie": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-3.0.4.tgz", + "integrity": "sha512-3rhx6RAIuRmCWJttnbgzMrp2TbHhUmgQ2GrpY/US03Siv5T28iXr2qYw1m3YqmluBxEyrvZaloVemkLSId+Oyg==", + "requires": { + "@types/cookie": "^0.3.1", + "@types/object-assign": "^4.0.30", + "cookie": "^0.3.1", + "object-assign": "^4.1.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", diff --git a/package.json b/package.json index db2cd0c..b7b0f60 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "axios": "^0.18.0", "bootstrap": "^4.1.3", "react": "^16.5.0", + "react-cookie": "^3.0.4", "react-dom": "^16.5.0", "react-icons": "^3.0.5", "react-router-dom": "^4.3.1", @@ -14,7 +15,7 @@ }, "scripts": { "start": "react-scripts start", - "build": "react-scripts build", + "build": "react-scripts build && ssh guarda 'rm -r www/darkou.fr/cfa/bo/static' && scp -r build/* guarda:www/darkou.fr/cfa/bo", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, diff --git a/src/Api.js b/src/Api.js index 60f9f40..5384520 100644 --- a/src/Api.js +++ b/src/Api.js @@ -1,9 +1,15 @@ import axios from 'axios'; +axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*'; + export function setDefaults(params) { axios.defaults.headers.common.Authorization = params.Authorization; } +export function setAuthorization(Authorization) { + axios.defaults.headers.common.Authorization = Authorization; +} + export default axios.create({ baseURL: 'https://api.cfa.darkou.fr/api/', }); diff --git a/src/App.js b/src/App.js index c612e08..891c7af 100644 --- a/src/App.js +++ b/src/App.js @@ -9,6 +9,7 @@ import Vegetable from './Vegetable'; import requireAuth from './requireAuth'; import Login from './Login'; +import Logout from './Logout'; import './App.css'; @@ -19,6 +20,7 @@ class App extends Component { + diff --git a/src/Categories.js b/src/Categories.js index bb81511..fedee20 100644 --- a/src/Categories.js +++ b/src/Categories.js @@ -9,6 +9,7 @@ import { } from 'reactstrap'; import { FaTrashAlt, FaPlus } from 'react-icons/fa'; import { Link } from 'react-router-dom'; +import Navigation from './Navigation'; import Header from './Header'; import API from './Api'; @@ -81,48 +82,51 @@ class Categories extends Component { render() { return ( - +
- - - - - - - - - - - {this.state.Categories.map((item, key) => ( - - - - - + + +
#NomNom d'élémentsAction
{item.id}{item.name}{item.Vegetables !== undefined ? item.Vegetables.length : 0 } - {' '} - -
+ + + + + + - ))} - -
#NomNom d'élémentsAction
-
- - - - -
- + + + {this.state.Categories.map((item, key) => ( + + {item.id} + {item.name} + {item.Vegetables !== undefined ? item.Vegetables.length : 0 } + + {' '} + + + + ))} + + +
+ + + + +
+ +
); } } diff --git a/src/Category.js b/src/Category.js index 9772d60..9a8c650 100644 --- a/src/Category.js +++ b/src/Category.js @@ -9,6 +9,7 @@ import { } from 'reactstrap'; import { FaTrashAlt, FaPlus, FaEdit } from 'react-icons/fa'; import { Link } from 'react-router-dom'; +import Navigation from './Navigation'; import Header from './Header'; import API from './Api'; @@ -111,61 +112,64 @@ class Category extends Component { render() { return ( - -
-
- - - - -
- - - - - - - - - - {this.state.Category.Vegetables && this.state.Category.Vegetables.map((item, key) => ( - - - - +
+
+ + +
+ + + + + +
#NomAction
{item.id}{item.name} - {' '} - -
+ + + + + - ))} - -
#NomAction
-
- - - - -
- + + + {this.state.Category.Vegetables && this.state.Category.Vegetables.map((item, key) => ( + + {item.id} + {item.name} + + {' '} + + + + ))} + + +
+ + + + +
+ + ); } } diff --git a/src/Header.js b/src/Header.js index 6482547..ae5eccb 100644 --- a/src/Header.js +++ b/src/Header.js @@ -1,77 +1,51 @@ import React from 'react'; -import { Breadcrumb, BreadcrumbItem } from 'reactstrap'; import { Link } from 'react-router-dom'; -import API from './Api'; +import { + Collapse, + Navbar, + NavbarToggler, + NavbarBrand, + Nav, + NavItem, + NavLink, +} from 'reactstrap'; +import { FaSignOutAlt } from 'react-icons/fa'; -class Header extends React.Component { +export default class Example extends React.Component { constructor(props) { super(props); - const Breadcrumb = []; - - if (API.defaults.headers.common.Authorization !== undefined) { - Breadcrumb.push({ - name: 'Catégories', - path: '/categories', - active: !this.props.categoryId, - }); - - if (this.props.categoryId) { - Breadcrumb.push({ - name: this.props.categoryId, - path: `/categories/${this.props.categoryId}`, - active: !this.props.vegetableId, - }); - - if (this.props.vegetableId) { - Breadcrumb.push({ - name: this.props.vegetableId, - path: `/categories/${this.props.categoryId}/vegetal/${this.props.vegetableId}`, - active: true, - }); - } - } - } - + this.toggle = this.toggle.bind(this); this.state = { - Breadcrumb, + isOpen: false, }; } - componentWillReceiveProps(props) { - if (props.categoryName) { - const Breadcrumb = this.state.Breadcrumb; - Breadcrumb[1].name = props.categoryName; - this.setState({ Breadcrumb }); - } - if (props.vegetableName) { - const Breadcrumb = this.state.Breadcrumb; - Breadcrumb[2].name = props.vegetableName; - this.setState({ Breadcrumb }); - } + toggle() { + this.setState({ + isOpen: !this.state.isOpen, + }); } render() { return (
- - { this.state.Breadcrumb.map((item, key) => ( - item.active === true - ? ( - - {item.name} - - ) - : ( - - {item.name} - - ) - ))} - + + RodiVert + + + + +
); } } - -export default Header; diff --git a/src/Login.js b/src/Login.js index 567b63f..c6499bc 100644 --- a/src/Login.js +++ b/src/Login.js @@ -10,7 +10,8 @@ import { Alert, } from 'reactstrap'; import { FaSignInAlt } from 'react-icons/fa'; -import API, { setDefaults } from './Api'; +import { Cookies } from 'react-cookie'; +import API, { setAuthorization } from './Api'; class Login extends Component { constructor(props) { @@ -37,9 +38,11 @@ class Login extends Component { }) .then((response) => { if (response.status === 200) { - setDefaults({ - Authorization: `Basic ${new Buffer(`${this.state.email}:${this.state.password}`).toString('base64')}`, - }); + const cookies = new Cookies(); + const Authorization = `Basic ${new Buffer(`${this.state.email}:${this.state.password}`).toString('base64')}`; + + cookies.set('cfa_bo', Authorization); + setAuthorization(Authorization); this.setState({ message: '' }); this.props.history.push('/categories'); } else { diff --git a/src/Logout.js b/src/Logout.js new file mode 100644 index 0000000..0b0ed8c --- /dev/null +++ b/src/Logout.js @@ -0,0 +1,23 @@ +import { Component } from 'react'; +import { Cookies } from 'react-cookie'; +import { setAuthorization } from './Api'; + +class Logout extends Component { + constructor(props) { + super(props); + const cookies = new Cookies(); + + setAuthorization(null); + cookies.remove('cfa_bo'); + + this.props.history.push('/'); + } + + render() { + return ( + 'Bye !' + ); + } +} + +export default Logout; diff --git a/src/Navigation.js b/src/Navigation.js new file mode 100644 index 0000000..59379bd --- /dev/null +++ b/src/Navigation.js @@ -0,0 +1,77 @@ +import React from 'react'; +import { Breadcrumb, BreadcrumbItem } from 'reactstrap'; +import { Link } from 'react-router-dom'; +import API from './Api'; + +class Navigation extends React.Component { + constructor(props) { + super(props); + + const Breadcrumb = []; + + if (API.defaults.headers.common.Authorization !== undefined) { + Breadcrumb.push({ + name: 'Catégories', + path: '/categories', + active: !this.props.categoryId, + }); + + if (this.props.categoryId) { + Breadcrumb.push({ + name: this.props.categoryId, + path: `/categories/${this.props.categoryId}`, + active: !this.props.vegetableId, + }); + + if (this.props.vegetableId) { + Breadcrumb.push({ + name: this.props.vegetableId, + path: `/categories/${this.props.categoryId}/vegetal/${this.props.vegetableId}`, + active: true, + }); + } + } + } + + this.state = { + Breadcrumb, + }; + } + + componentWillReceiveProps(props) { + if (props.categoryName) { + const Breadcrumb = this.state.Breadcrumb; + Breadcrumb[1].name = props.categoryName; + this.setState({ Breadcrumb }); + } + if (props.vegetableName) { + const Breadcrumb = this.state.Breadcrumb; + Breadcrumb[2].name = props.vegetableName; + this.setState({ Breadcrumb }); + } + } + + render() { + return ( +
+ + { this.state.Breadcrumb.map((item, key) => ( + item.active === true + ? ( + + {item.name} + + ) + : ( + + {item.name} + + ) + ))} + +
+ ); + } +} + +export default Navigation; diff --git a/src/Vegetable.js b/src/Vegetable.js index 0562a00..ce603b7 100644 --- a/src/Vegetable.js +++ b/src/Vegetable.js @@ -10,6 +10,7 @@ import { Input, } from 'reactstrap'; import { FaEdit, FaMapMarkerAlt } from 'react-icons/fa'; +import Navigation from './Navigation'; import Header from './Header'; import API from './Api'; @@ -161,100 +162,103 @@ class Vegetable extends Component { } return ( - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - this.onImageChange(e)} - /> - - -
- {$imagePreview} -
- - - -
-
-
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this.onImageChange(e)} + /> + + +
+ {$imagePreview}
-
- - - - - + + +
+
+
+
+
+ + + + + + +
); } } diff --git a/src/index.js b/src/index.js index e7cad07..1f9da4b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,19 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { Cookies } from 'react-cookie'; import App from './App'; import registerServiceWorker from './registerServiceWorker'; +import { setAuthorization } from './Api'; import './index.css'; import 'bootstrap/dist/css/bootstrap.min.css'; +const cookies = new Cookies(); +const auth = cookies.get('cfa_bo'); + +if (auth) { + setAuthorization(auth); +} + ReactDOM.render(, document.getElementById('root')); registerServiceWorker();