I have a application where I have two logins one for superAdmin
and other for 'Admin'.
I have several pages One which is common (home page) both users have excess to that.
then I have several other pages which are some for admin
and others are for superAdmin
.
Now when I open my page I am trying to go '/' this route (My home route). What I am trying to do
Now If I am logged in as admin and admin user is typing some superAdmin
url in address bar I want that to be redirect to current admin route
Same goes for superAdmin
as well
both the user I want to restrict to excess each-others route
And if I am admin user or superAdmin user and trying to logged in and trying to excess authenticated route I should be redirect to home page
What I have done
I have created one component (Dynamic route) here I am checking what user is trying to do.
and in route.js in my routing file I am passing props as guest
,superAdmin
and admin
Dynamicroute.js code
I have created my context to store the user once they logged in
export default function Dynamicroute(props) {
const { user } = useAuthState(); // this I am getting from my context
console.log(user);
if (props.partner && !user) {
console.log('admin not logedin');
return <Redirect to="/admin" />;
} else if (props.admin && !user) {
console.log('superAdmin not loged in');
return <Redirect to="/superAdmin" />;
} else if (props.admin && user.role === 'admin') {
console.log('admin logedin');
return <Redirect to="/admin_home" />;
} else if (props.admin && user.role === 'superAdmin') {
console.log('super admin loged in');
return <Redirect to="/superadmin_home" />;
} else if (props.guest && user) {
console.log('guest');
return <Redirect to="/" />;
} else {
return <Route component={props.component} {...props} />;
}
}
My route.js
<DuynamicRoute exact path="/" component={Home} guest />
<DuynamicRoute path="/admin" component={loginAdmin} guest />
<DuynamicRoute path="/superAdmin" component={loginSuperAdmin} guest />
<DuynamicRoute path="/admin_home" component={admin_home} admin/>
<DuynamicRoute path="/superAdmin_home" component={superAdmin_home} superAdmin/>
Issue I am facing
I don't know what issue I am facing it is redirecting me to that route on login but content is not loading If I console something on that page I am not able to get that, the page is getting blank.
I am following this lecture from 25:00 timing
Edited
Here is my code sand box
Please do check this
Edit
admin and super admin are going to be loged in different browsers, So just do not want admin to access super admin and vice-versa if they type in url each other's rout
For better management and development of the program along with the best practices, Do the Authorization in React.js as follows:
Demo on Codesandbox
First: You need a class
for checking permissions
and routes/pages configs
like below:
class AppUtils {
static setRoutes(config) {
let routes = [...config.routes];
if (config.auth) {
routes = routes.map((route) => {
let auth = config.auth ? [...config.auth] : null;
auth = route.auth ? [...auth, ...route.auth] : auth;
return {
...route,
auth
};
});
}
return [...routes];
}
static generateRoutesFromConfigs(configs) {
let allRoutes = [];
configs.forEach((config) => {
allRoutes = [...allRoutes, ...this.setRoutes(config)];
});
return allRoutes;
}
static hasPermission(authArr, userRole) {
/**
* If auth array is not defined
* Pass and allow
*/
if (authArr === null || authArr === undefined) {
// console.info("auth is null || undefined:", authArr);
return true;
} else if (authArr.length === 0) {
/**
* if auth array is empty means,
* allow only user role is guest (null or empty[])
*/
// console.info("auth is empty[]:", authArr);
return !userRole || userRole.length === 0;
} else {
/**
* Check if user has grants
*/
// console.info("auth arr:", authArr);
/*
Check if user role is array,
*/
if (userRole && Array.isArray(userRole)) {
return authArr.some((r) => userRole.indexOf(r) >= 0);
}
/*
Check if user role is string,
*/
return authArr.includes(userRole);
}
}
}
export default AppUtils;
Second: You need Authorization component for handling routes like below:
import React, { Component } from "react";
import AppUtils from "utils/AppUtils";
import { matchRoutes } from "react-router-config";
import { withRouter } from "react-router-dom";
import AppContext from "context/AppContext";
class AppAuthorization extends Component {
constructor(props, context) {
super(props);
const { routes } = context;
this.state = {
accessGranted: true,
routes
};
}
componentDidMount() {
if (!this.state.accessGranted) {
this.redirectRoute();
}
}
componentDidUpdate() {
if (!this.state.accessGranted) {
this.redirectRoute();
}
}
static getDerivedStateFromProps(props, state) {
const { location, userRole } = props;
const { pathname } = location;
const matched = matchRoutes(state.routes, pathname)[0];
return {
accessGranted: matched
? AppUtils.hasPermission(matched.route.auth, userRole)
: true
};
}
shouldComponentUpdate(nextProps, nextState) {
return nextState.accessGranted !== this.state.accessGranted;
}
redirectRoute() {
const { location, userRole, history } = this.props;
const { pathname, state } = location;
const redirectUrl = state && state.redirectUrl ? state.redirectUrl : "/";
/*
User is guest
Redirect to Login Page
*/
if (!userRole || userRole.length === 0) {
history.push({
pathname: "/login",
state: { redirectUrl: pathname }
});
} else {
/*
User is member
User must be on unAuthorized page or just logged in
Redirect to dashboard or redirectUrl
*/
history.push({
pathname: redirectUrl
});
}
}
render() {
// console.info('App Authorization rendered', accessGranted);
return this.state.accessGranted ? (
<React.Fragment>{this.props.children}</React.Fragment>
) : null;
}
}
// AppAuthorization.defaultProps = {
// userRole: [] // You can manage roles by redux or any state managements
// };
AppAuthorization.contextType = AppContext;
export default withRouter(AppAuthorization);
Third: You need authRoles file or remote for managing roles on client like below:
/**
* Authorization Roles
*/
const authRoles = {
admin: ["admin"],
superAdmin: ["superAdmin"],
user: ["user"],
onlyGuest: []
};
export default authRoles;
Forth: If you want to move forward with this logic, you have to implement the structure of your pages as follows:
src
|---pages
|---home
|---HomePage.jsx
|---HomePageConfig.jsx
|
|- The rest of the pages should be implemented in the same way
For example: When you want to implement a page that only the admin can see (admin home page config):
import React from "react";
import authRoles from "auth/authRoles";
export const AdminHomePageConfig = {
auth: authRoles.admin,
routes: [
{
path: "/admin",
exact: true,
component: React.lazy(() => import("./HomePage"))
}
]
};
Or the home page that everyone can see:
import React from "react";
export const HomePageConfig = {
routes: [
{
path: "/",
exact: true,
component: React.lazy(() => import("./HomePage"))
}
]
};
According to the example above, you can enter the auth prop
with the role
here, to restrict access to the page.
To get a closer look at this logic, I implemented it in the Codesandbox, which you can see via the link below:
Demo on Codesandbox
Notice: The above demo needs to be more complete, and instead of storing user roles in the state, it is better to use state management packages (redux, ...) and also perform login operations through cookies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With