Fork of the excellent esp8266-react - https://github.com/rjwats/esp8266-react
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.2 KiB

  1. import * as React from 'react';
  2. import history from '../history'
  3. import { withNotifier } from '../components/SnackbarNotification';
  4. import { VERIFY_AUTHORIZATION_ENDPOINT } from '../constants/Endpoints';
  5. import { ACCESS_TOKEN, authorizedFetch } from './Authentication';
  6. import { AuthenticationContext } from './Context';
  7. import jwtDecode from 'jwt-decode';
  8. import CircularProgress from '@material-ui/core/CircularProgress';
  9. import Typography from '@material-ui/core/Typography';
  10. import { withStyles } from '@material-ui/core/styles';
  11. const styles = theme => ({
  12. loadingPanel: {
  13. padding: theme.spacing.unit * 2,
  14. display: "flex",
  15. alignItems: "center",
  16. justifyContent: "center",
  17. height: "100vh",
  18. flexDirection: "column"
  19. },
  20. progress: {
  21. margin: theme.spacing.unit * 4,
  22. }
  23. });
  24. class AuthenticationWrapper extends React.Component {
  25. constructor(props) {
  26. super(props);
  27. this.refresh = this.refresh.bind(this);
  28. this.signIn = this.signIn.bind(this);
  29. this.signOut = this.signOut.bind(this);
  30. this.state = {
  31. context: {
  32. refresh: this.refresh,
  33. signIn: this.signIn,
  34. signOut: this.signOut
  35. },
  36. initialized: false
  37. };
  38. }
  39. componentDidMount() {
  40. this.refresh();
  41. }
  42. render() {
  43. return (
  44. <React.Fragment>
  45. {this.state.initialized ? this.renderContent() : this.renderContentLoading()}
  46. </React.Fragment>
  47. );
  48. }
  49. renderContent() {
  50. return (
  51. <AuthenticationContext.Provider value={this.state.context}>
  52. {this.props.children}
  53. </AuthenticationContext.Provider>
  54. );
  55. }
  56. renderContentLoading() {
  57. const { classes } = this.props;
  58. return (
  59. <div className={classes.loadingPanel}>
  60. <CircularProgress className={classes.progress} size={100} />
  61. <Typography variant="h4" >
  62. Loading...
  63. </Typography>
  64. </div>
  65. );
  66. }
  67. refresh() {
  68. var accessToken = localStorage.getItem(ACCESS_TOKEN);
  69. if (accessToken) {
  70. authorizedFetch(VERIFY_AUTHORIZATION_ENDPOINT)
  71. .then(response => {
  72. const jwt = response.status === 200 ? jwtDecode(accessToken) : undefined;
  73. this.setState({ initialized: true, context: { ...this.state.context, jwt } });
  74. }).catch(error => {
  75. this.setState({ initialized: true, context: { ...this.state.context, jwt: undefined } });
  76. this.props.raiseNotification("Error verifying authorization: " + error.message);
  77. });
  78. } else {
  79. this.setState({ initialized: true, context: { ...this.state.context, jwt: undefined } });
  80. }
  81. }
  82. signIn(accessToken) {
  83. try {
  84. this.setState({ context: { ...this.state.context, jwt: jwtDecode(accessToken) } });
  85. localStorage.setItem(ACCESS_TOKEN, accessToken);
  86. } catch (err) {
  87. this.setState({ initialized: true, context: { ...this.state.context, jwt: undefined } });
  88. this.props.raiseNotification("Failed to parse JWT " + err.message);
  89. }
  90. }
  91. signOut() {
  92. localStorage.removeItem(ACCESS_TOKEN);
  93. this.setState({
  94. context: {
  95. ...this.state.context,
  96. jwt: undefined
  97. }
  98. });
  99. this.props.raiseNotification("You have signed out.");
  100. history.push('/');
  101. }
  102. }
  103. export default withStyles(styles)(withNotifier(AuthenticationWrapper))