Handling User Roles - reactjs

I have created a server-less React App with Firebase for Hosting, Database and User-Authentication.
Now let us assume I have three roles : student, teacher and (you guessed it) admin.
I am currently doing this to show components specific to roles :
/*
Get user data from the database which has a 'type' field with one of the above values,
then in a child render function :
*/
{this.props.userData.type === 'student' &&
//Show components for students
}
{this.props.userData.type === 'teacher' &&
//Show components for teacher
}
Now the way I see it, the user could open Chrome Dev Tools and use React Dev Tools to change the prop value to one of the others.
I came across using the 'Can' component by defining roles and permissions but that essentially does the same thing and the user can alter the prop passed to the 'Can' component to access content of another role.
Solutions I have considered :
Use obscure values for the 'type' field like random numbers or words instead of the obvious teacher/student.
Store list of uids under each role in database and check if current uid exists under the list and pass some prop hidden in some unsuspecting object or under a random name, something of that sort.
Create entirely different routes and set redirects so that the user doesn't have enough time to change the props or state since the component which redirects is no longer mounted.
Questions :
Is there a better way to structure my app so that I won't have to use state or props to identify user type?
Am I on the right path or is there something so obvious that I'm missing?
Edit :
I understand that there is nothing I can do to stop the user from editing the state or props of the components. Answers suggest that I should validate user type on the server to check if the user can perform an action. Is there a way I can achieve this on my current setup (see first line)? Or is it necessary to have a server.js?

The visitor will always be able to somehow "hack" your frontend application (eg. by changing the props in React Dev Tools or in any other way).
It is completely okay for web to work like this, as all your main logic should be located on the backend, where you can actually prevent some actions to happen.
A very similar question has been asked here How to prevent html/JavaScript code modification

Roles should not matter in the browser beyond aesthetic reasons (show/hide button etc). Your access-control should be done in the backed with functions and rules.
Any malicious user can edit HTML, or send an HTTP request to pretend that they have a role. However, on the backend you should check if the user-id actually has that role or not and reject running code you're not supposed to.

Related

Advice on setting up a marketplace app in React Native

I want to create a marketplace app which displays a different user flow (UI UX) when a customer or seller logs in. How can i achieve this with React Native?
Is this classed as a multi tenant app?
As an absolute beginner, i would appreciate some advice and possibly links to documentation on how to set up the structure using Visual Studio Code. Thanks.
Create a different set of routes for both seller and customer via route authorization.
You can use state management such as mobx or redux,set seller or customer on launch,so every screen or component can request at any time if wether a seller or customer then render the right things
As someone mentioned, redux or different routes after authorization might be what you want. But it sounds like you may have bigger picture issues/questions. The front end could certainly be written in react native, but you need a back-end where the data will live and users will be authorized. If you don't want to write that yourself, you might consider Firebase, as its easy to use and free up to a certain usage level.
Firebase handles authorization easily; then when people are creating accounts, have them specify if they're sellers, etc, and save that to user profiles. When they log in, use the data in their user profile to direct them to different react navigation stacks or just different themes or whatever your needs are.

Is it done with Local-storage ? or data-binding in React JS?

I am new to react and developing the react application, where I want that user can save his/her selected values on the frontend and later on can also see those values via clicking a button and user can see what values have been selected previously. now the question is how to provide this functionality, I have studied that either it could be done by local-storage or by the data binding concept in react, but I have no clue which one is best to implement in my scenario.
Let me explain to you with the help of a diagram.
(The first Image with Indicator Generation)This is the main page of my React Application, under the section of "Question & Indicator" there is a thing called Associated Indicator, these are the values which user have select itself on the Frontend side.
(The second image with detailed user-controls) This is the page where all the user-controls are defined, here user can select the values and at the end when user clicked "Associate" it will be associated and the values have been shown under the section of Associated Indicators, from that user when clicking any of the associated indicators it will show all the values selected by user on front end.
Cheers.
Preserving data in a web app is not related to React -or any other front end technology specifically.
Data binding is a concept on how to update your views when certain data changes, and it is not related at all to how data should be saved. But related to how modern front end technologies like react and angular render your components.
You can save data in a web app using different methods, each one is suitable for certain use cases - and so you should use the one that suits you.
For example you can use any of the following:
Cookies: old way of saving data on the front end, can stay infinitely but can also be deleted if the user decided to delete them or clear data from his browser. Cookies Get send to the server-side with each request done with the browser, has limitations with size.
IndexedDB: This one is literally like a database inside the browser, really fast when querying data, also has bigger Size limitations than both Cookies, and LocalStorage. However, this is a really low level API. Won't recommend to use it, unless you really need its features. Can also stay infinitely, and can also be deleted by user.
LocalStorage: New browser API to persist data, much more easier to handle than Cookies And IndexedDB, Can stay infinitely, but can also be deleted by the user. Has bigger size limits than Cookies, but less than IndexedDb.
SessionStorage: Data saved for each tab, and data cleared when page session ends.
Finally If You want data that persist for forever and the user can't delete it, you have to do your own solution in the backend.

withAuthenticator signup complete

In my react native app, currently i'm using an AWS/Amplify withAuthenticator to make sure a user is signed up. The very first time a user signs up, i'd like to call a function once and once only, to create to store some user date elsewhere. Currently this code pulls up a standard AWS signup screen (i don't know where the code for it is hidden), where the user signs up:
export default withAuthenticator(App, { includeGreetings: true});
The first time this user is successfully created in AWS, how can i find out its complete and then also call my own function? This function never need be called again.
You should move that functionally into the aws lambads.
This link describes how you can achieve that easily with the aws cognito dashboard. This enables you not only to set some state within a store from that lambda function, but you can also send them a mail or notify you that a new user singed up.
The other way, described here, is to write your own components to handle sign up. This also enables you to do something on user confirmation. This is a lot more complicated but it depends on your use case.
Hope this helps. Happy coding.

SPA - When to use Location Based or Internal State?

Hopefully this is not too opinionated but I am wondering if there are best practices regarding location-based SPAs and Internal based SPAs.
Internal based SPAs - track state internally
Location-based SPAs - URL location / Sessions , etc
In one part of my site if a user pastes in the url the search results will show.
However if I should be doing it for areas like admin section.
For instance I am allow users to add inventory to this point
admin -> add new Inventory -> choose center -> choose subcategory -> add inventory.
This is pretty much the flow, however if I would make it location based then on the "add inventory page" I would have to set the
company
center
subcategory
Which would require ajax requests to get all the data and basically every page I would have to do setting up data. It just seems like alot of work that every page has to be fully setup if they are coming from a url.
I am already using stuff like react-router to do my routing but in the end of the day I would to make sure that everything is always setup to the page can basically run standalone.
So maybe in some situations it would be better to somehow just redirect users back to the root of everything instead?
I would recommend using React Context for resolving your problem.
Once authorized, you can set the Provider value to be the user or their permissions, then on each ComponentDidMount or render() or whatever lifecycle hook you choose, you can check the users permissions and then allow the functionalities based on that.
Context values persist throughout routing, so you won't have to worry about updating it all the time (although you probably should if your user has a timed session).
So it is fully possible and probably more effective to use a mix of both internal and location based state management.

How to keep state when receiving server push via websockets?

I have a react/flux application with websockets that works fine. All communication happens inside my WebSocketUtils file. Whenever I receive new data from my server as push events I trigger an action and let the whole Flux flow happen. In the end that causes my view to rerender.
The individual views are connected to my store via Higher Order Components. All new data is passed into my view as props. As these are changeable I use these props and set them as my initial state (which is ok).
Now let's say I have user A and user B looking at the same view of my application (on different machines of course).
User A edits some data
User B also edits some data
User A saves this new data
User B receives new data via push event and the view will rerender
Problem: User B lost all the data that was edited but not yet saved.
Any ideas how to solve this problem?
User WiredPrairie is correct in their comment. This isn't a React or Web Sockets problem, it's a problem with conflict resolution.
What would you expect to see in that situation? You would want the two states to be kept temporarily until you can either merge them automatically (unlikely) or present the user with some kind of interface to review their changes.
You could also prompt user B that user A is editing their data, just to keep them informed :)
A granular approach to editing would help - like in a Google Spreadsheet a user will often only edit a cell at a time, so in your situation you may only send field-level information across the wire (as opposed to record-level), and that would help avoid conflicts.
At the end of the day though, this is less about specific technology and more about your application: you need to work out how you'd like it to behave.

Resources