Merge pull request #2287 from influxdata/multitenancy_purgatory

Purgatory
pull/10616/head
Alex Paxton 2017-11-07 23:33:12 -08:00 committed by GitHub
commit 7841f14c8b
5 changed files with 132 additions and 10 deletions

View File

@ -47,6 +47,10 @@ const CheckSources = React.createClass({
auth: shape({ auth: shape({
isUsingAuth: bool, isUsingAuth: bool,
me: shape(), me: shape(),
currentOrganization: shape({
name: string.isRequired,
id: string.isRequired,
}),
}), }),
}, },
@ -106,8 +110,8 @@ const CheckSources = React.createClass({
const restString = rest === null ? DEFAULT_HOME_PAGE : rest[1] const restString = rest === null ? DEFAULT_HOME_PAGE : rest[1]
if (isUsingAuth && me.role === MEMBER_ROLE) { if (isUsingAuth && me.role === MEMBER_ROLE) {
// if you're a member, go to limbo. // if you're a member, go to purgatory.
return router.push('/limbo') return router.push('/purgatory')
} }
if (isUsingAuth && me.role === VIEWER_ROLE) { if (isUsingAuth && me.role === VIEWER_ROLE) {
@ -116,8 +120,8 @@ const CheckSources = React.createClass({
} else if (sources[0]) { } else if (sources[0]) {
return router.push(`/sources/${sources[0].id}/${restString}`) return router.push(`/sources/${sources[0].id}/${restString}`)
} }
// if you're a viewer and there are no sources, go to limbo. // if you're a viewer and there are no sources, go to purgatory.
return router.push('/limbo') return router.push('/purgatory')
} }
// if you're an editor or not using auth, try for sources or otherwise // if you're an editor or not using auth, try for sources or otherwise
@ -142,7 +146,11 @@ const CheckSources = React.createClass({
}, },
render() { render() {
const {params, sources, auth: {isUsingAuth, me}} = this.props const {
params,
sources,
auth: {isUsingAuth, me, currentOrganization},
} = this.props
const {isFetching} = this.state const {isFetching} = this.state
const source = sources.find(s => s.id === params.sourceID) const source = sources.find(s => s.id === params.sourceID)
@ -150,7 +158,8 @@ const CheckSources = React.createClass({
isFetching || isFetching ||
!source || !source ||
typeof isUsingAuth !== 'boolean' || typeof isUsingAuth !== 'boolean' ||
(me && me.role === undefined) // TODO: not sure this happens (me && me.role === undefined) || // TODO: not sure this happens
!currentOrganization
) { ) {
return <div className="page-spinner" /> return <div className="page-spinner" />
} }

70
ui/src/auth/Purgatory.js Normal file
View File

@ -0,0 +1,70 @@
import React, {PropTypes} from 'react'
import {connect} from 'react-redux'
import {MEMBER_ROLE} from 'src/auth/Authorized'
const memberCopy = (
<p>This role does not grant you sufficient permissions to view Chronograf.</p>
)
const viewerCopy = (
<p>
This organization does not have any configured sources<br />and your role
does not have permission to configure a source.
</p>
)
const Purgatory = ({name, provider, scheme, currentOrganization, role}) =>
<div>
<div className="auth-page">
<div className="auth-box">
<div className="auth-logo" />
<div className="auth--purgatory">
<h3>
Logged in to <strong>{currentOrganization.name}</strong> as a{' '}
<em>{role}</em>.
</h3>
{role === MEMBER_ROLE ? memberCopy : viewerCopy}
<p>Contact your Administrator for assistance.</p>
<hr />
<pre>
<code>
username: {name}
<br />
provider: {provider}
<br />
scheme: {scheme}
</code>
</pre>
</div>
</div>
<p className="auth-credits">
Made by <span className="icon cubo-uniform" />InfluxData
</p>
<div className="auth-image" />
</div>
</div>
const {shape, string} = PropTypes
Purgatory.propTypes = {
name: string.isRequired,
provider: string.isRequired,
scheme: string.isRequired,
currentOrganization: shape({
id: string.isRequired,
name: string.isRequired,
}).isRequired,
role: string.isRequired,
}
const mapStateToProps = ({
auth: {me: {name, provider, scheme, currentOrganization, role}},
}) => ({
name,
provider,
scheme,
currentOrganization,
role,
})
export default connect(mapStateToProps)(Purgatory)

View File

@ -1,7 +1,15 @@
import Login from './Login' import Login from './Login'
import Purgatory from './Purgatory'
import { import {
UserIsAuthenticated, UserIsAuthenticated,
Authenticated, Authenticated,
UserIsNotAuthenticated, UserIsNotAuthenticated,
} from './Authenticated' } from './Authenticated'
export {Login, UserIsAuthenticated, Authenticated, UserIsNotAuthenticated} export {
Login,
Purgatory,
UserIsAuthenticated,
Authenticated,
UserIsNotAuthenticated,
}

View File

@ -11,7 +11,12 @@ import configureStore from 'src/store/configureStore'
import {loadLocalStorage} from 'src/localStorage' import {loadLocalStorage} from 'src/localStorage'
import App from 'src/App' import App from 'src/App'
import {Login, UserIsAuthenticated, UserIsNotAuthenticated} from 'src/auth' import {
Login,
UserIsAuthenticated,
UserIsNotAuthenticated,
Purgatory,
} from 'src/auth'
import CheckSources from 'src/CheckSources' import CheckSources from 'src/CheckSources'
import {StatusPage} from 'src/status' import {StatusPage} from 'src/status'
import {HostsPage, HostPage} from 'src/hosts' import {HostsPage, HostPage} from 'src/hosts'
@ -141,6 +146,7 @@ const Root = React.createClass({
<Router history={history}> <Router history={history}>
<Route path="/" component={UserIsAuthenticated(CheckSources)} /> <Route path="/" component={UserIsAuthenticated(CheckSources)} />
<Route path="/login" component={UserIsNotAuthenticated(Login)} /> <Route path="/login" component={UserIsNotAuthenticated(Login)} />
<Route path="/purgatory" component={UserIsAuthenticated(Purgatory)} />
<Route <Route
path="/sources/new" path="/sources/new"
component={UserIsAuthenticated(SourcePage)} component={UserIsAuthenticated(SourcePage)}

View File

@ -38,12 +38,14 @@
h1 { h1 {
color: $g20-white; color: $g20-white;
@include no-user-select();
font-weight: 200; font-weight: 200;
font-size: 52px; font-size: 52px;
letter-spacing: -2px; letter-spacing: -2px;
} }
p { p {
color: $g11-sidewalk; color: $g11-sidewalk;
@include no-user-select();
} }
.btn { .btn {
@ -65,12 +67,14 @@
height: 100px; height: 100px;
} }
.auth-credits { .auth-credits {
@include no-user-select();
font-weight: 600;
z-index: 90; z-index: 90;
position: absolute; position: absolute;
bottom: ($sidebar--width / 4); bottom: ($sidebar--width / 4);
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
font-size: 12px; font-size: 13px;
color: $g11-sidewalk; color: $g11-sidewalk;
.icon { .icon {
@ -78,6 +82,31 @@
vertical-align: middle; vertical-align: middle;
position: relative; position: relative;
top: -1px; top: -1px;
margin-right: 1px; margin-right: 2px;
}
}
/* Purgatory */
.auth--purgatory {
margin-top: 30px;
min-width: 400px;
background-color: $g3-castle;
border-radius: 4px;
min-height: 200px;
padding: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
> h3 {
white-space: nowrap;
}
> p {
text-align: center;
}
hr {
width: 100%;
} }
} }