Home Reference Source

src/core/auth/SecurityCheck.jsx

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { getContext, compose } from 'recompose';
import { createStructuredSelector } from 'reselect';
import { isEqual, omit } from 'lodash';
import { userSelector } from '../../selectors/auth';
import { SECURITY_CHECK } from './authTypes';
import { dataRequestWidget } from '../../actions/widgets';

/**
 * <SecurityCheck config={{roles: ['admin'], context: ['ivanov']]}}
 *                render={(permissions, err) => permissions ? <Input /> : <Alert message={err.message} />}
 */
class SecurityCheck extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      permissions: null,
      error: null,
    };
  }

  async componentDidMount() {
    await this.checkPermissions(this.props);
  }

  componentWillReceiveProps(nextProps) {
    if (
      !isEqual(nextProps.user, this.props.user) ||
      !isEqual(nextProps.config, this.props.config)
    ) {
      this.checkPermissions(nextProps);
    }
  }

  async checkPermissions(params) {
    const { authProvider, config, user } = params;
    const { onPermissionsSet } = this.props;
    try {
      const permissions = await authProvider(SECURITY_CHECK, {
        config,
        user,
      });
      this.setState(
        { permissions, error: null },
        () => onPermissionsSet && onPermissionsSet(permissions)
      );
    } catch (error) {
      this.setState(
        { permissions: null, error },
        () => onPermissionsSet && onPermissionsSet(null)
      );
    }
  }

  render() {
    const { permissions } = this.state;
    const props = omit(this.props, ['authProvider', 'config']);
    return this.props.render({ permissions, ...props });
  }
}

SecurityCheck.propTypes = {
  authProvider: PropTypes.func,
  config: PropTypes.object,
  user: PropTypes.object,
  render: PropTypes.func,
};

SecurityCheck.defaultProps = {
  onPermissionsSet: () => {},
};

const mapStateToProps = createStructuredSelector({
  user: userSelector,
});

export default compose(
  getContext({
    authProvider: PropTypes.func,
  }),
  connect(mapStateToProps)
)(SecurityCheck);