diff --git a/new-lamassu-admin/src/pazuz/App.js b/new-lamassu-admin/src/pazuz/App.js
index 3baed658..32b9c44d 100644
--- a/new-lamassu-admin/src/pazuz/App.js
+++ b/new-lamassu-admin/src/pazuz/App.js
@@ -1,15 +1,17 @@
+import { useQuery } from '@apollo/react-hooks'
import CssBaseline from '@material-ui/core/CssBaseline'
import Grid from '@material-ui/core/Grid'
+import Slide from '@material-ui/core/Slide'
import {
StylesProvider,
jssPreset,
MuiThemeProvider,
makeStyles
} from '@material-ui/core/styles'
-import { axios } from '@use-hooks/axios'
+import gql from 'graphql-tag'
import { create } from 'jss'
import extendJss from 'jss-plugin-extend'
-import React, { useContext, useEffect, useState } from 'react'
+import React, { useContext, useState } from 'react'
import {
useLocation,
useHistory,
@@ -69,11 +71,32 @@ const useStyles = makeStyles({
}
})
+const GET_USER_DATA = gql`
+ query userData {
+ userData {
+ id
+ username
+ role
+ enabled
+ last_accessed
+ last_accessed_from
+ last_accessed_address
+ }
+ }
+`
+
const Main = () => {
const classes = useStyles()
const location = useLocation()
const history = useHistory()
- const { wizardTested, userData } = useContext(AppContext)
+ const { wizardTested, userData, setUserData } = useContext(AppContext)
+
+ const { loading } = useQuery(GET_USER_DATA, {
+ onCompleted: userResponse => {
+ if (!userData && userResponse?.userData)
+ setUserData(userResponse.userData)
+ }
+ })
const route = location.pathname
@@ -97,7 +120,17 @@ const Main = () => {
)}
{sidebar && !is404 && wizardTested && (
-
+
+
+
+ }
+ />
)}
@@ -109,9 +142,7 @@ const Main = () => {
onClick={onClick}
/>
)}
-
-
-
+ {!loading && }
@@ -121,46 +152,26 @@ const Main = () => {
const App = () => {
const [wizardTested, setWizardTested] = useState(false)
const [userData, setUserData] = useState(null)
- const [loading, setLoading] = useState(true)
- const url =
- process.env.NODE_ENV === 'development' ? 'https://localhost:8070' : ''
-
- useEffect(() => {
- getUserData()
- }, [])
-
- const getUserData = () => {
- axios({
- method: 'GET',
- url: `${url}/user-data`,
- withCredentials: true
- })
- .then(res => {
- setLoading(false)
- if (res.status === 200) setUserData(res.data.user)
- })
- .catch(err => {
- setLoading(false)
- if (err.status === 403) setUserData(null)
- })
+ const setRole = role => {
+ if (userData && userData.role !== role) {
+ setUserData({ ...userData, role })
+ }
}
return (
- {!loading && (
-
-
-
-
-
-
-
-
-
-
- )}
+ value={{ wizardTested, setWizardTested, userData, setUserData, setRole }}>
+
+
+
+
+
+
+
+
+
+
)
}
diff --git a/new-lamassu-admin/src/pazuz/apollo/Provider.js b/new-lamassu-admin/src/pazuz/apollo/Provider.js
index 1dfaa322..5512815d 100644
--- a/new-lamassu-admin/src/pazuz/apollo/Provider.js
+++ b/new-lamassu-admin/src/pazuz/apollo/Provider.js
@@ -4,20 +4,23 @@ import { ApolloClient } from 'apollo-client'
import { ApolloLink } from 'apollo-link'
import { onError } from 'apollo-link-error'
import { HttpLink } from 'apollo-link-http'
-import React from 'react'
+import React, { useContext } from 'react'
import { useHistory, useLocation } from 'react-router-dom'
+import AppContext from 'src/AppContext'
+
const URI =
process.env.NODE_ENV === 'development' ? 'https://localhost:8070' : ''
-const getClient = (history, location) =>
+const getClient = (history, location, setUserData, setRole) =>
new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path, extensions }) => {
if (extensions?.code === 'UNAUTHENTICATED') {
- if (location.pathname !== '/404') history.push('/404')
+ setUserData(null)
+ if (location.pathname !== '/login') history.push('/login')
}
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
@@ -25,6 +28,21 @@ const getClient = (history, location) =>
})
if (networkError) console.log(`[Network error]: ${networkError}`)
}),
+ new ApolloLink((operation, forward) => {
+ return forward(operation).map(response => {
+ const context = operation.getContext()
+ const {
+ response: { headers }
+ } = context
+
+ if (headers) {
+ const role = headers.get('role')
+ setRole(role)
+ }
+
+ return response
+ })
+ }),
new HttpLink({
credentials: 'include',
uri: `${URI}/graphql`
@@ -49,7 +67,9 @@ const getClient = (history, location) =>
const Provider = ({ children }) => {
const history = useHistory()
const location = useLocation()
- const client = getClient(history, location)
+ const { setUserData, setRole } = useContext(AppContext)
+ const client = getClient(history, location, setUserData, setRole)
+
return {children}
}
diff --git a/new-lamassu-admin/src/pazuz/routing/routes.js b/new-lamassu-admin/src/pazuz/routing/routes.js
index 323b938e..1656dcb6 100644
--- a/new-lamassu-admin/src/pazuz/routing/routes.js
+++ b/new-lamassu-admin/src/pazuz/routing/routes.js
@@ -5,7 +5,6 @@ import * as R from 'ramda'
import React, { useContext } from 'react'
import {
matchPath,
- Route,
Redirect,
Switch,
useHistory,
@@ -13,11 +12,14 @@ import {
} from 'react-router-dom'
import AppContext from 'src/AppContext'
-import AuthRegister from 'src/pages/AuthRegister'
+import Login from 'src/pages/Authentication/Login'
+import Register from 'src/pages/Authentication/Register'
+import Reset2FA from 'src/pages/Authentication/Reset2FA'
+import ResetPassword from 'src/pages/Authentication/ResetPassword'
import Blacklist from 'src/pages/Blacklist'
import Cashout from 'src/pages/Cashout'
import Commissions from 'src/pages/Commissions'
-import ConfigMigration from 'src/pages/ConfigMigration'
+// import ConfigMigration from 'src/pages/ConfigMigration'
import { Customers, CustomerProfile } from 'src/pages/Customers'
import Dashboard from 'src/pages/Dashboard'
import Funding from 'src/pages/Funding'
@@ -34,9 +36,14 @@ import ReceiptPrinting from 'src/pages/OperatorInfo/ReceiptPrinting'
import TermsConditions from 'src/pages/OperatorInfo/TermsConditions'
import ServerLogs from 'src/pages/ServerLogs'
import Services from 'src/pages/Services/Services'
+import SessionManagement from 'src/pages/SessionManagement/SessionManagement'
import Transactions from 'src/pages/Transactions/Transactions'
import Triggers from 'src/pages/Triggers'
+import UserManagement from 'src/pages/UserManagement/UserManagement'
import Wizard from 'src/pages/Wizard'
+import PrivateRoute from 'src/routing/PrivateRoute'
+import PublicRoute from 'src/routing/PublicRoute'
+import { ROLES } from 'src/routing/utils'
import { namespaces } from 'src/utils/config'
const useStyles = makeStyles({
@@ -53,12 +60,14 @@ const tree = [
key: 'transactions',
label: 'Transactions',
route: '/transactions',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Transactions
},
{
key: 'maintenance',
label: 'Maintenance',
route: '/maintenance',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
get component() {
return () =>
},
@@ -67,30 +76,35 @@ const tree = [
key: 'cash_cassettes',
label: 'Cash Cassettes',
route: '/maintenance/cash-cassettes',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: CashCassettes
},
{
key: 'funding',
label: 'Funding',
route: '/maintenance/funding',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Funding
},
{
key: 'logs',
label: 'Machine Logs',
route: '/maintenance/logs',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: MachineLogs
},
{
key: 'machine-status',
label: 'Machine Status',
route: '/maintenance/machine-status',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: MachineStatus
},
{
key: 'server-logs',
label: 'Server',
route: '/maintenance/server-logs',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: ServerLogs
}
]
@@ -99,6 +113,7 @@ const tree = [
key: 'settings',
label: 'Settings',
route: '/settings',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
get component() {
return () =>
},
@@ -107,30 +122,35 @@ const tree = [
key: namespaces.COMMISSIONS,
label: 'Commissions',
route: '/settings/commissions',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Commissions
},
{
key: namespaces.LOCALE,
label: 'Locales',
route: '/settings/locale',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Locales
},
{
key: namespaces.CASH_OUT,
label: 'Cash-out',
route: '/settings/cash-out',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Cashout
},
{
key: namespaces.NOTIFICATIONS,
label: 'Notifications',
route: '/settings/notifications',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Notifications
},
{
key: 'services',
label: '3rd party services',
route: '/settings/3rd-party-services',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Services
},
{
@@ -138,6 +158,7 @@ const tree = [
label: 'Operator Info',
route: '/settings/operator-info',
title: 'Operator Information',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
get component() {
return () => (
},
@@ -189,32 +215,62 @@ const tree = [
key: 'triggers',
label: 'Triggers',
route: '/compliance/triggers',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Triggers
},
{
key: 'customers',
label: 'Customers',
route: '/compliance/customers',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Customers
},
{
key: 'blacklist',
label: 'Blacklist',
route: '/compliance/blacklist',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: Blacklist
},
{
key: 'promo-codes',
label: 'Promo Codes',
route: '/compliance/loyalty/codes',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: PromoCodes
},
{
key: 'customer',
route: '/compliance/customer/:id',
+ allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: CustomerProfile
}
]
+ },
+ {
+ key: 'system',
+ label: 'System',
+ route: '/system',
+ allowedRoles: [ROLES.SUPERUSER],
+ get component() {
+ return () =>
+ },
+ children: [
+ {
+ key: 'user-management',
+ label: 'User Management',
+ route: '/system/user-management',
+ allowedRoles: [ROLES.SUPERUSER],
+ component: UserManagement
+ },
+ {
+ key: 'session-management',
+ label: 'Session Management',
+ route: '/system/session-management',
+ allowedRoles: [ROLES.SUPERUSER],
+ component: SessionManagement
+ }
+ ]
}
]
@@ -252,13 +308,29 @@ const Routes = () => {
const history = useHistory()
const location = useLocation()
+ const { wizardTested, userData } = useContext(AppContext)
- const { wizardTested } = useContext(AppContext)
-
- const dontTriggerPages = ['/404', '/register', '/wizard']
+ const dontTriggerPages = [
+ '/404',
+ '/register',
+ '/wizard',
+ '/login',
+ '/register',
+ '/resetpassword',
+ '/reset2fa'
+ ]
if (!wizardTested && !R.contains(location.pathname)(dontTriggerPages)) {
history.push('/wizard')
+ return null
+ }
+
+ const getFilteredRoutes = () => {
+ if (!userData) return []
+ return flattened.filter(value => {
+ const keys = value.allowedRoles
+ return R.includes(userData.role, keys)
+ })
}
const Transition = location.state ? Slide : Fade
@@ -276,10 +348,10 @@ const Routes = () => {
return (
-
+
-
-
+
+
{
}
/>
-
-
-
-
-
- {flattened.map(({ route, component: Page, key }) => (
-
+
+
+
+
+ {/* */}
+
+
+
+ {getFilteredRoutes().map(({ route, component: Page, key }) => (
+
{
}
/>
-
+
))}
-
-
+
+
-
+
)
}