How to handle user permission base on role? - reactjs

I'm creating an Admin Dashboard with React, and manage access base on user role (Admin, Client and User). Each role will have permission like:
Admin: can view Dashboard and CRUD posts
Client: can view Dashboard and create and read posts
User: can't view Dashboard and only read posts
Is there a way to implement this or npm package that supports with role n permission like this?
thanks!
this is demo code
https://codesandbox.io/s/hardcore-shape-6mvos?file=/src/App.tsx

In your case to handle react rendering your best chose is NextJs
By NextJs you can controller your rendering page before sending to your client

I deal with this every day. I have a component called Permission. It takes in the name of the permission(s) as a prop and checks to see if the user (stored in redux) has those permissions. If so, it returns the children of the Permission component.
Permission.js:
const Permission = ({ allowedPermissions, children }) => {
function isVisible() {
let visible = true;
allowedPermission.forEach((permission) => {
if (!user.permissions.includes(permission) {
visible = false;
}
});
return visible;
}
return isVisible() ? children : null;
}
Usage, which can include being wrapped around react-router switch/route statements:
<Permission allowedPermissions=["admin"]>
<Button onClick={() => deletePost()}>Delete</Button>
</Permission>

Related

How to secure a component in Reactjs?

I have created two React components, Login, and Secure. Login hosts the FacebookLogin component found in this package: https://www.npmjs.com/package/#greatsumini/react-facebook-login, and I get a successful response from Facebook by the login attempt when the button is pressed. This is supposed to navigate to the Secure page when successful.
The problem is that I can just navigate directly to the Secure component in the URL, (I'm using react-router-dom package for this), but I want any attempt to navigate to a secure page to be redirected to the Login page.
How can I do this?
According to that component's documentation, you can get the login status in code:
FacebookLoginClient.login((res) => {
// "res" contains information about the current user's logged-in status
});
So in any component that needs to know the status, simply reference the library:
import { FacebookLoginClient } from '#greatsumini/react-facebook-login';
And use that FacebookLoginClient.login to check the user's logged-in status. If the status doesn't meet the criteria you define, redirect the user. (For example, you can check this in a useEffect when the component first loads, or perhaps on every render if you're paranoid about it.)
For more detail on rendering the target component, since useEffect occurs after the initial render, you can rely on additional state to check. For example, consider this structure:
const [canRender, setCanRender] = useState(false);
useEffect(() => {
FacebookLoginClient.login((res) => {
// check the status and call "setCanRender" accordingly
});
}, []);
if (!canRender) return <>Checking authentication...</>;
// your existing return for the component goes here
The idea here is to default the component to a kind of "loading state" and only render the "secure" content after the authentication has been verified.

Can I redirect in Next.js passing data?

I want to be able to redirect to another page in Next.js passing data. The reason about why I want to do it is the following:
I am working on a project in which the user can be an entity or not. If it is not an entity the page about the user will be / and if it is an entity the page about the user will be /entity.
When I go to the page / I use getServerSideProps to fetch all the data about the user and send it as a prop. However, if the fetched user is an entity I redirect to /entity. Then, I use getServerSideProps in /entity to fetch all the data about the user (that is an entity).
I am doing two requests when I only should do one of them. If I manage to redirect to /entity passing the data that I already fetched I wouldn't have this problem. Is there a way I can do it?
// index.js
export async function getServerSideProps(context) {
const user = await getUser(accessCookies(context));
if (user.isEntity)
return { redirect: { destination: "/entity", permanent: false } }; // Would like to send user
return { props: { user} };
}
I don't see any way to achieve it and I don't even know if it is possible.

Reactjs: Show logged in or log in accordingly to session

I am trying to get better in react and I would like to do it everything correctly which is why I am asking for your opinions and help.
I am building a project in NextJS and I have a layout component which contains components which are rendered multiple times such as header, footer etc.
I this header, I have a "Sign in" and "Sign out" button. I'd like it to only show one of them accordingly to your session status.
I use a sessionid which contains some more info in the database and this sessionid is stored in a httponly cookie.
It is stored in the database with data:
id
sessionid
userid
expires
Would you add or remove anything to this?
So my question is:
How would you check for a session and then render x accordingly? Would you just send an api call each request that checks the session or? Should I maybe use useContext and create a provider which can then send the session with the provider?
I'm quite lost on how to do it the best way so the flow is smooth as f*ck.
It depends how strict you want to be with it.
One option would be to simply check the existence of the cookie and adjust according to that. You can use js-cookie for that.
The better option, in my opinion, is to verify the cookie with your backend. You should set up an endpoint that simply verifies / parses the cookie and returns something like the user_id, or ismply a boolean indicating whether the user is logged in.
Given that you are using Next, you can add this call to your App's getInitialProps() like this:
App.getInitialProps = async () => {
let loggedIn;
try {
({ data: {loggedIn} } = await axios.get('/api/v1/auth/checkCookie'));
} catch (err) {
console.log('Error checkingCookie', err.message );
}
return {
loggedIn,
}
}
Your loggedIn variable will then be available in the props of your App, like:
function App({currentUser}) {
if (currentUser) {
return <div>Logged In</div>
} else {
return <div>Logged Out</div>
}
}

User role based routes

I'm using react for my frontend
I'm having a login, forgot password in my routing
Based on user type I need to include a few sets of routes
Ex
User Type
Student:
Dashboard, Profile, View Attendance
Teacher :
Dashboard, Profile, add Attendance, Student Profile
After login then only I know user type.
If I load all the routes while rendering the app component, unwanted routes are loaded.
So the student can use the Teacher component. This might leads to problems.
How to rid of this problem
You could use react-authorization to wrap the component in the route and allow only users in specific roles to view it. You can also define an error component which would be displayed to an unauthorized user. Here's an example (in TypeScript):
const AdministrationRoute: React.FC<AdministrationRouteProps> = props => {
const accessDeniedError = <div className="ml-3 mr-3"><Alert
color="danger">Access denied!</Alert></div>;
return <IfGranted expected="ROLE_ADMIN" actual={props.user.roles} unauthorized={accessDeniedError}>
<Users/>
</IfGranted>;
};
And then use the component in a route as usual:
<Route path={Routes.administration.path} component={AdministrationRoute}/>
DISCLAIMER: I am the author of the react-authorization library.

Display logged in user's first name onto page (from database)

In preparing a welcome page after a user has logged in, I'd like the page title to display their first name which is found in the user ID database (e.g - "Welcome, Sally!"). This is a bit different than just using a cookie to relay the username in a location; like for example in the top corner to access user settings.
The site is being built with React, if that affects the code needed.
Any suggestions?
are you asking how to get the username in the app state? or just how you would render that?
if you already have the firstname in an auth object in state you could do something like this:
class WelcomePage extends Component {
render() {
const { auth } = this.props
var pageTitle = `Welcome, { auth.firstname }`
return (
<h1>{ pageTitle }</h1>
)
}
}
export default WelcomePage
otherwise I would need more information to understand what you're asking
Here is a solution I worked out that seems to do the job. This lies within the React component for the page rendering.
render: function(){
var user = JSON.parse(localStorage.getItem('user'));
...
return (
<div>
<h2>Welcome, {user.firstname1}!</h2>
</div>
Here's a quick screen shot of the result ("Candy" being the logged-in user's first name):

Resources