From 1dc53d5759335a4ac8c0891dc0dcfd42c807aeca Mon Sep 17 00:00:00 2001 From: Will Piers Date: Wed, 16 Nov 2016 14:26:08 -0800 Subject: [PATCH] Setting up structure for Auth flow --- ui/src/auth/CheckAuth.js | 36 +++++ ui/src/auth/Login.js | 12 ++ ui/src/auth/index.js | 3 + ui/src/index.js | 84 ++++-------- .../shared/components/AddClusterAccounts.js | 79 ----------- .../shared/components/AddPermissionModal.js | 124 ------------------ ui/src/shared/components/ClusterError.js | 24 ---- .../components/InsufficientPermissions.js | 21 --- ui/src/shared/components/NoClusterError.js | 35 ----- .../shared/components/NoClusterLinksError.js | 27 ---- ui/src/shared/components/PermissionsTable.js | 76 ----------- ui/src/shared/components/RolePanels.js | 86 ------------ ui/src/shared/components/UsersTable.js | 95 -------------- 13 files changed, 74 insertions(+), 628 deletions(-) create mode 100644 ui/src/auth/CheckAuth.js create mode 100644 ui/src/auth/Login.js create mode 100644 ui/src/auth/index.js delete mode 100644 ui/src/shared/components/AddClusterAccounts.js delete mode 100644 ui/src/shared/components/AddPermissionModal.js delete mode 100644 ui/src/shared/components/ClusterError.js delete mode 100644 ui/src/shared/components/InsufficientPermissions.js delete mode 100644 ui/src/shared/components/NoClusterError.js delete mode 100644 ui/src/shared/components/NoClusterLinksError.js delete mode 100644 ui/src/shared/components/PermissionsTable.js delete mode 100644 ui/src/shared/components/RolePanels.js delete mode 100644 ui/src/shared/components/UsersTable.js diff --git a/ui/src/auth/CheckAuth.js b/ui/src/auth/CheckAuth.js new file mode 100644 index 000000000..7b8ee5f4d --- /dev/null +++ b/ui/src/auth/CheckAuth.js @@ -0,0 +1,36 @@ +import React, {PropTypes} from 'react'; +import {withRouter} from 'react-router'; + +const CheckAuth = React.createClass({ + propTypes: { + router: PropTypes.shape({ + push: PropTypes.func.isRequired, + }).isRequired, + children: PropTypes.node.isRequired, + }, + + getInitialState() { + return { + loggedIn: false, + }; + }, + + componentDidMount() { + // console.log('checking auth'); + // this.setState({ + // loggedIn: true, + // }); + this.props.router.push('/login'); + }, + + render() { + const {loggedIn} = this.state; + if (!loggedIn) { + return
AUTH IS BEING CHECKED
; + } + + return this.props.children; + }, +}); + +export default withRouter(CheckAuth); diff --git a/ui/src/auth/Login.js b/ui/src/auth/Login.js new file mode 100644 index 000000000..5aae11af3 --- /dev/null +++ b/ui/src/auth/Login.js @@ -0,0 +1,12 @@ +import React from 'react'; +import {withRouter} from 'react-router'; + +const Login = React.createClass({ + render() { + return ( + Click me to log in + ); + }, +}); + +export default withRouter(Login); diff --git a/ui/src/auth/index.js b/ui/src/auth/index.js new file mode 100644 index 000000000..bddc865ec --- /dev/null +++ b/ui/src/auth/index.js @@ -0,0 +1,3 @@ +import Login from './Login'; +import CheckAuth from './CheckAuth'; +export {Login, CheckAuth}; diff --git a/ui/src/index.js b/ui/src/index.js index 4863b6146..4dd74ba98 100644 --- a/ui/src/index.js +++ b/ui/src/index.js @@ -1,4 +1,4 @@ -import React, {PropTypes} from 'react'; +import React from 'react'; import {render} from 'react-dom'; import {Provider} from 'react-redux'; import {Router, Route, browserHistory} from 'react-router'; @@ -8,18 +8,16 @@ import AlertsApp from 'src/alerts'; import CheckSources from 'src/CheckSources'; import {HostsPage, HostPage} from 'src/hosts'; import {KubernetesPage} from 'src/kubernetes'; +import {CheckAuth, Login} from 'src/auth'; import {KapacitorPage, KapacitorRulePage, KapacitorRulesPage, KapacitorTasksPage} from 'src/kapacitor'; import DataExplorer from 'src/chronograf'; import {CreateSource, SourceForm, ManageSources} from 'src/sources'; import NotFound from 'src/shared/components/NotFound'; -import NoClusterError from 'src/shared/components/NoClusterError'; import configureStore from 'src/store/configureStore'; import {getSources} from 'shared/apis'; import 'src/style/enterprise_style/application.scss'; -const {number, shape, string, bool} = PropTypes; - const defaultTimeRange = {upper: null, lower: 'now() - 15m'}; const lsTimeRange = window.localStorage.getItem('timeRange'); const parsedTimeRange = JSON.parse(lsTimeRange) || {}; @@ -28,38 +26,7 @@ const timeRange = Object.assign(defaultTimeRange, parsedTimeRange); const store = configureStore({timeRange}); const rootNode = document.getElementById('react-root'); -const HTTP_SERVER_ERROR = 500; - const Root = React.createClass({ - getInitialState() { - return { - me: { - id: 1, - name: 'Chronograf', - email: 'foo@example.com', - admin: true, - }, - isFetching: false, - hasReadPermission: false, - clusterStatus: null, - }; - }, - - childContextTypes: { - me: shape({ - id: number.isRequired, - name: string.isRequired, - email: string.isRequired, - admin: bool.isRequired, - }), - }, - - getChildContext() { - return { - me: this.state.me, - }; - }, - activeSource(sources) { const defaultSource = sources.find((s) => s.default); if (defaultSource && defaultSource.id) { @@ -79,36 +46,31 @@ const Root = React.createClass({ }, render() { - if (this.state.isFetching) { - return null; - } - - if (this.state.clusterStatus === HTTP_SERVER_ERROR) { - return ; - } - return ( - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - diff --git a/ui/src/shared/components/AddClusterAccounts.js b/ui/src/shared/components/AddClusterAccounts.js deleted file mode 100644 index 8dea74cc2..000000000 --- a/ui/src/shared/components/AddClusterAccounts.js +++ /dev/null @@ -1,79 +0,0 @@ -import React, {PropTypes} from 'react'; - -const {arrayOf, number, shape, func, string} = PropTypes; - -const AddClusterAccounts = React.createClass({ - propTypes: { - clusters: arrayOf(shape({ - id: number.isRequired, - cluster_users: arrayOf(shape({ - name: string.isRequired, - })), - dipslay_name: string, - cluster_id: string.isRequired, - })).isRequired, - onSelectClusterAccount: func.isRequired, - headerText: string, - }, - - getDefaultProps() { - return { - headerText: 'Pair With Cluster Accounts', - }; - }, - - handleSelectClusterAccount(e, clusterID) { - this.props.onSelectClusterAccount({ - clusterID, - accountName: e.target.value, - }); - }, - - render() { - return ( -
- { - this.props.clusters.map((cluster, i) => { - return ( -
-
- {i === 0 ? : null} -
- {cluster.display_name || cluster.cluster_id} -
-
-
- {i === 0 ? : null} - {this.renderClusterUsers(cluster)} -
-
- ); - }) - } -
- ); - }, - - renderClusterUsers(cluster) { - if (!cluster.cluster_users) { - return ( - - ); - } - - return ( - - ); - }, -}); - -export default AddClusterAccounts; diff --git a/ui/src/shared/components/AddPermissionModal.js b/ui/src/shared/components/AddPermissionModal.js deleted file mode 100644 index 911fd1032..000000000 --- a/ui/src/shared/components/AddPermissionModal.js +++ /dev/null @@ -1,124 +0,0 @@ -import React, {PropTypes} from 'react'; - -const CLUSTER_WIDE_PERMISSIONS = ["CreateDatabase", "AddRemoveNode", "ManageShard", "DropDatabase", "CopyShard", "Rebalance"]; - -const AddPermissionModal = React.createClass({ - propTypes: { - activeCluster: PropTypes.string.isRequired, - permissions: PropTypes.arrayOf(PropTypes.shape({ - name: PropTypes.string.isRequired, - displayName: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - })), - databases: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired, - onAddPermission: PropTypes.func.isRequired, - }, - - getInitialState() { - return { - selectedPermission: null, - selectedDatabase: '', - }; - }, - - handlePermissionClick(permission) { - this.setState({ - selectedPermission: permission, - selectedDatabase: '', - }); - }, - - handleDatabaseChange(e) { - this.setState({selectedDatabase: e.target.value}); - }, - - handleSubmit(e) { - e.preventDefault(); - this.props.onAddPermission({ - name: this.state.selectedPermission, - resources: [this.state.selectedDatabase], - }); - $('#addPermissionModal').modal('hide'); // eslint-disable-line no-undef - }, - - render() { - const {permissions} = this.props; - - return ( - - ); - }, - - renderFooter() { - return ( -
- - -
- ); - }, - - renderOptions() { - return ( -
- {this.state.selectedPermission ? this.renderDatabases() : null} -
- ); - }, - - renderDatabases() { - const isClusterWide = CLUSTER_WIDE_PERMISSIONS.includes(this.state.selectedPermission); - if (!this.props.databases.length || isClusterWide) { - return null; - } - - return ( -
-
-
- - -
-
-
- ); - }, -}); - -export default AddPermissionModal; diff --git a/ui/src/shared/components/ClusterError.js b/ui/src/shared/components/ClusterError.js deleted file mode 100644 index f3dd4c923..000000000 --- a/ui/src/shared/components/ClusterError.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; - -const {node} = React.PropTypes; -const ClusterError = React.createClass({ - propTypes: { - children: node.isRequired, - }, - - render() { - return ( -
-
-
-
- {this.props.children} -
-
-
-
- ); - }, -}); - -export default ClusterError; diff --git a/ui/src/shared/components/InsufficientPermissions.js b/ui/src/shared/components/InsufficientPermissions.js deleted file mode 100644 index 7626a77f5..000000000 --- a/ui/src/shared/components/InsufficientPermissions.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import ClusterError from './ClusterError'; - -const InsufficientPermissions = React.createClass({ - render() { - return ( - -
-

- {`Your account has insufficient permissions`} -

-
-
-

Talk to your admin to get additional permissions for access

-
-
- ); - }, -}); - -export default InsufficientPermissions; diff --git a/ui/src/shared/components/NoClusterError.js b/ui/src/shared/components/NoClusterError.js deleted file mode 100644 index b55ecd33c..000000000 --- a/ui/src/shared/components/NoClusterError.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import errorCopy from 'hson!shared/copy/errors.hson'; - -const NoClusterError = React.createClass({ - render() { - return ( -
-
-
-
-
-
-

- {errorCopy.noCluster.head} -

-
-
-

How to resolve:

-

- {errorCopy.noCluster.body} -

-
- -
-
-
-
-
-
-
- ); - }, -}); - -export default NoClusterError; diff --git a/ui/src/shared/components/NoClusterLinksError.js b/ui/src/shared/components/NoClusterLinksError.js deleted file mode 100644 index 72b92dea6..000000000 --- a/ui/src/shared/components/NoClusterLinksError.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; - -const NoClusterLinksError = React.createClass({ - render() { - return ( -
-
-
-
-
-

- This user is not associated with any cluster accounts! -

-
-
-

Many features in Chronograf require your user to be associated with a cluster account.

-

Ask an administrator to associate your user with a cluster account.

-
-
-
-
-
- ); - }, -}); - -export default NoClusterLinksError; diff --git a/ui/src/shared/components/PermissionsTable.js b/ui/src/shared/components/PermissionsTable.js deleted file mode 100644 index 105ed42ee..000000000 --- a/ui/src/shared/components/PermissionsTable.js +++ /dev/null @@ -1,76 +0,0 @@ -import React, {PropTypes} from 'react'; - -const {arrayOf, shape, string} = PropTypes; - -const PermissionsTable = React.createClass({ - propTypes: { - permissions: PropTypes.arrayOf(shape({ - name: string.isRequired, - displayName: string.isRequired, - description: string.isRequired, - resources: arrayOf(string.isRequired).isRequired, - })).isRequired, - showAddResource: PropTypes.bool, - onRemovePermission: PropTypes.func, - }, - - getDefaultProps() { - return { - permissions: [], - showAddResource: false, - }; - }, - - handleAddResourceClick() { - // TODO - }, - - handleRemovePermission(permission) { - this.props.onRemovePermission(permission); - }, - - render() { - if (!this.props.permissions.length) { - return ( -
- -

This Role has no Permissions

-
- ); - } - - return ( -
- - - {this.props.permissions.map((p) => ( - - - - {this.props.onRemovePermission ? ( - - ) : null} - - ))} - -
{p.displayName} - {p.resources.map((resource, i) =>
{resource === '' ? 'All Databases' : resource}
)} - {this.props.showAddResource ? ( -
- -
- ) : null} -
- -
-
- ); - }, -}); - -export default PermissionsTable; diff --git a/ui/src/shared/components/RolePanels.js b/ui/src/shared/components/RolePanels.js deleted file mode 100644 index c8ebfeedc..000000000 --- a/ui/src/shared/components/RolePanels.js +++ /dev/null @@ -1,86 +0,0 @@ -import React, {PropTypes} from 'react'; -import {Link} from 'react-router'; -import PermissionsTable from 'src/shared/components/PermissionsTable'; - -const {arrayOf, bool, func, shape, string} = PropTypes; - -const RolePanels = React.createClass({ - propTypes: { - roles: arrayOf(shape({ - name: string.isRequired, - users: arrayOf(string.isRequired).isRequired, - permissions: arrayOf(shape({ - name: string.isRequired, - displayName: string.isRequired, - description: string.isRequired, - resources: arrayOf(string.isRequired).isRequired, - })).isRequired, - })).isRequired, - showUserCount: bool, - onRemoveAccountFromRole: func, - }, - - getDefaultProps() { - return { - showUserCount: false, - }; - }, - - render() { - const {roles} = this.props; - - if (!roles.length) { - return ( -
-
-
- -

This user has no roles

-
-
-
- ); - } - - return ( -
- {roles.map((role) => { - const id = role.name.replace(/[^\w]/gi, ''); - return ( -
- -
- -
-
- ); - })} -
- ); - }, -}); - -export default RolePanels; diff --git a/ui/src/shared/components/UsersTable.js b/ui/src/shared/components/UsersTable.js deleted file mode 100644 index 656478e4b..000000000 --- a/ui/src/shared/components/UsersTable.js +++ /dev/null @@ -1,95 +0,0 @@ -import React, {PropTypes} from 'react'; -import {Link} from 'react-router'; -import classNames from 'classnames'; - -const {func, shape, arrayOf, string} = PropTypes; -const UsersTable = React.createClass({ - propTypes: { - users: arrayOf(shape({}).isRequired).isRequired, - activeCluster: string.isRequired, - onUserToDelete: func.isRequired, - me: shape({}).isRequired, - deleteText: string, - }, - - getDefaultProps() { - return { - deleteText: 'Delete', - }; - }, - - handleSelectUserToDelete(user) { - this.props.onUserToDelete(user); - }, - render() { - const {users, activeCluster, me} = this.props; - - if (!users.length) { - return ( -
- -

No users

-
- ); - } - - return ( - - - - - - - - - - { - users.map((user) => { - const isMe = me.id === user.id; - return ( - - - - - - - - ); - }) - } - -
NameAdminEmail
- - {user.name} - {isMe ? (You) : null} - - {this.renderAdminIcon(user.admin)}{user.email} - {this.renderDeleteButton(user)} -
- ); - }, - - renderAdminIcon(isAdmin) { - return ; - }, - - renderDeleteButton(user) { - if (this.props.me.id === user.id) { - return ; - } - - return ( - - ); - }, -}); - -export default UsersTable;