Commit 4981d37b authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Merge branch 'v1-oasis-login' into 'v1.0.0'

Added a global login for oasis with allowed users.

See merge request !453
parents a36082f0 bf010f59
Pipeline #115247 passed with stages
in 26 minutes and 59 seconds
......@@ -28,7 +28,7 @@ import { KeycloakProvider } from 'react-keycloak'
import { MuiThemeProvider } from '@material-ui/core/styles'
import { ErrorSnacks, ErrorBoundary } from './errors'
import Navigation from './nav/Navigation'
import { APIProvider } from './api'
import { APIProvider, GlobalLoginRequired } from './api'
const keycloak = Keycloak({
url: keycloakBase,
......@@ -47,7 +47,9 @@ export default function App() {
<MuiThemeProvider theme={nomadTheme}>
<ErrorSnacks>
<ErrorBoundary>
<Navigation />
<GlobalLoginRequired>
<Navigation />
</GlobalLoginRequired>
</ErrorBoundary>
</ErrorSnacks>
</MuiThemeProvider>
......
......@@ -23,8 +23,8 @@ import {
useRecoilState
} from 'recoil'
import PropTypes from 'prop-types'
import { apiBase } from '../config'
import { makeStyles, Typography } from '@material-ui/core'
import { apiBase, globalLoginRequired } from '../config'
import { Box, makeStyles, Typography } from '@material-ui/core'
import LoginLogout from './LoginLogout'
import { useKeycloak } from 'react-keycloak'
import axios from 'axios'
......@@ -465,6 +465,58 @@ export function useSetLoading() {
return useSetRecoilState(apiLoading)
}
function VerifyGlobalLogin({children}) {
const {api} = useApi()
const [verified, setVerified] = useState(null)
useEffect(() => {
api.get('users/me').then(() => setVerified(true)).catch(() => setVerified(false))
}, [api, setVerified])
if (verified === null) {
return ''
}
if (!verified) {
return <Box margin={2}>
<LoginLogout color="primary" />
<Typography color="error">
You are not allowed to access this NOMAD installation. Please logout and try again.
</Typography>
</Box>
}
return <React.Fragment>
{children}
</React.Fragment>
}
VerifyGlobalLogin.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired
}
export function GlobalLoginRequired({children}) {
if (!globalLoginRequired) {
return <React.Fragment>
{children}
</React.Fragment>
}
return <LoginRequired message="You have to be logged in to use this NOMAD installation.">
<VerifyGlobalLogin>
{children}
</VerifyGlobalLogin>
</LoginRequired>
}
GlobalLoginRequired.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired
}
const useLoginRequiredStyles = makeStyles(theme => ({
root: {
padding: theme.spacing(2),
......
......@@ -306,6 +306,9 @@ const SearchBar = React.memo(({
}
setSuggestions(res)
})
.catch((error) => {
console.log(error)
})
.finally(() => setLoading(false))
}, [api])
const suggestionDebounced = useCallback(debounce(suggestionCall, suggestionDebounceTime), [])
......
......@@ -518,6 +518,7 @@ export const SearchContext = React.memo(({
const setLocked = useSetRecoilState(lockedState)
const setStatistics = useSetRecoilState(statisticsState)
const {api} = useApi()
const {raiseErrors} = useErrors()
const setInitialAggs = useSetRecoilState(initialAggsState)
// Reset the query/locks when entering the search context for the first time
......@@ -580,7 +581,8 @@ export const SearchContext = React.memo(({
}
setInitialAggs(newData)
})
}, [api, setInitialAggs, resource])
.catch(raiseErrors)
}, [api, raiseErrors, setInitialAggs, resource])
const values = useMemo(() => ({
resource,
......@@ -1133,6 +1135,7 @@ export function useInitialAgg(name) {
*/
export function useAgg(name, update = true, restrict = undefined, delay = 500) {
const {api} = useApi()
const {raiseErrors} = useErrors()
const { resource } = useSearchContext()
const [results, setResults] = useState(undefined)
const initialAggs = useRecoilValue(initialAggsState)
......@@ -1182,7 +1185,8 @@ export function useAgg(name, update = true, restrict = undefined, delay = 500) {
firstLoad.current = false
setResults(newData)
})
}, [api, name, finalRestrict, resource])
.then(raiseErrors)
}, [api, raiseErrors, name, finalRestrict, resource])
// This is a debounced version of apiCall.
const debounced = useCallback(debounce(apiCall, delay), [])
......
......@@ -146,6 +146,9 @@ const InputText = React.memo(({
setSuggestions(res)
setOpen(true)
})
.catch((error) => {
console.log(error)
})
.finally(() => setLoading(false))
} else if (autocomplete === 'aggregations') {
}
......
......@@ -31,6 +31,7 @@ export const debug = window.nomadEnv.debug || false
export const encyclopediaEnabled = window.nomadEnv.encyclopediaEnabled || false
export const aitoolkitEnabled = window.nomadEnv.aitoolkitEnabled || false
export const oasis = window.nomadEnv.oasis || false
export const globalLoginRequired = window.nomadEnv.globalLoginRequired || false
export const email = 'support@nomad-lab.eu'
export const maxLogsToShow = 50
......
......@@ -87,7 +87,7 @@ def create_user_dependency(
status_code=status.HTTP_401_UNAUTHORIZED,
detail='Authentication is required for this Oasis',
headers={'WWW-Authenticate': 'Bearer'})
if user.email not in config.oasis.allowed_users:
if user.email not in config.oasis.allowed_users and user.username not in config.oasis.allowed_users:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail='You are not authorized to access this Oasis',
......
......@@ -264,6 +264,7 @@ window.nomadEnv = {{
'aitoolkitEnabled': {'true' if config.aitoolkit_enabled else 'false'},
'oasis': {'true' if config.keycloak.oasis else 'false'},
'version': {json.dumps(config.meta.beta) if config.meta.beta else dict()}
'globalLoginRequired': {'false' if config.oasis.allowed_users is None else 'true'}
}};''')
# replace base path in all GUI files
......
......@@ -193,6 +193,7 @@ class Keycloak():
return datamodel.User(
user_id=user_id,
email=payload.get('email', None),
username=payload.get('preferred_username', None),
first_name=payload.get('given_name', None),
last_name=payload.get('family_name', None))
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment