The javascript project I'm working on provides a way for users to purchase a "virtual" item, which allows them to access to the information about it. For example, purchasing a recipe.
The way I've structured my database is the following;
Database:
Reference:
Item:
Item Information
Users:
Purchases:
Item
When the customer purchases something, a function runs that copies the order data into the "Users" string, as a purchase. From here, I need a way for the user to be granted access to the "Item" object in the reference section to see the "Item Information", to see the information about what was just purchased.
Is there something similar to a list of authorised users in the security rules that can be dynamically changed to achieve this?
There is nothing built into Firebase Authentication of Firebase Realtime Database (or its security rules) for this, but you can likely build it on top.
If you want to grant the user access to each item that they purchased, you'd have rules that look something like this:
{
"rules": {
"Items": {
"$itemId": {
".read": "root.child('Users').child(auth.uid).child('Purchases').child($itemId).exists()"
}
}
}
}
So the .read rule here checks if the item the user is trying to read also exists under the list or Purchases for that user in the database.
Related
I have a custom claim "admin" attached to each user, carrying a boolean.
Now, in my frontend i am trying to generate a list of all admins.
For that i need to access all users who have said custom claim set to "true" and put them in an array, which i can then generate the list from.
The array should just look like the following:
const admins = ref([
{
uid: *uid of admin1*,
name: *name of admin1*,
},
{
uid: *uid of admin2*,
name: *name of admin2*,
},
...
])
So the following problems arise:
How do i access all users with said custom claim set to true, so that i can loop over them and populate my array?
Is this a case for a cloud function, so that it can not be manipulated?
I tried reading this Firebase documentation, however i could not make sense of it.
How do i access all users with said custom claim set to true, so that i can loop over them and populate my array?
There is no direct way to query users based on custom claims.
Is this a case for a cloud function?
Yes, you would have to list all users as in the documentation that you've shared and check for custom claims for each user separately.
It might be best to use a database like Firestore or Realtime Database and maintain a collection of all admins. Make sure this cannot be updated from client side directly using security rules.
i am trying to think of a database for a project similar to netflix. where you can login on multiple devices and for each device you have a token.
the problem is that i cannot think of a structure of a relational database for that.
i created it on mongodb and my structure was like that:
{
user: 'name',
etc...
tokens: [{
token: 'asdasijdoaisjd',
token: 'sodjio2n'
}]
}
so yeah... everytime a user logins in a new token gets added to the db and when he logs out from one place, one token gets deleted.
how can i create something similar in a relational database?
there is two ways to do that
add a column in your users table called tokens for example and save all of the tokens as JSON data
[Recomended] make a new table called users_tokens and make a relation of on to many between the user to tokens table and in the users_tokens table you will add a column called user_id to easily get all tokens that belong to the user
At last, you can read about how to implement one-to-many relation with sequelize here
I'm building an application whereby if a user wishes to add an item to a personal watchlist, they must be logged in. I use localStorage to store this personal watchlist data and to retrieve it. The problem I am having is that if account 'A' adds an item to their watchlist and then logs out and account 'B' then logs in, the previous stored data is returned from account 'A'.
How can I prevent this from happening so that the data is only saved/returned for each particular user account? Should I be using something instead of localStorage like sessionStorage? Any help is appreciated.
I've solved this personally by including an identifier for the user in the local storage key. You'll have an entry per user and do the lookup based on the identifier. Something like:
localStorage.setItem(`watchlist:${user.id}`, data) // set
const watchlist = localStorage.getItem(`watchlist:${user.id}`) // get
As noted by #AlexB in the comments, be aware that multiple users on the same device will have the local data of any other users in their localStorage, so be sure to consider privacy.
Save your data with userId as key(unique for all user) and corresponding watchlist as data
localStorage.setItem('userId', data);
and then fetch it with the login user Id
localStorage.getItem('loginUserId');
I have a clientside rendered frontend with a REST API. The frontend should render some elements based on the user authorization. Example permissions could be
delete users
being able to delete supervisors too
create users
add users to workflows
...
A huge amount of permissions is managed by an administrator. My question is:
How would you get to know what permissions you have for this rendered page and what to render?
The only idea that comes to my mind would be to create an API endpoint /user/:id/permissions and ask for every permission the user has. An example response object could be
[
{
"permissionId": 0,
"description": "Has access to page"
},
{
"permissionId": 1,
"description": "Can create users"
},
{
"permissionId": 2,
"description": "Can delete users"
}
// ...
]
Then I could start rendering my HTML based on these permissions (Pseudo code / I normally use VueJs)
<button render-if="permissions.contains(1)">This shows up if the user can create users</button>
<button render-if="permissions.contains(2)">This shows up if the user can delete other users</button>
I think the frontend code might get a bit messy. The API endpoint should be fine but maybe there is a better solution. Does a best practise solution already exist?
Your approach (having a separate permissions endpoint) is a good way to handle this.
Another alternative is to use a hypermedia format like HAL or Siren. Whenever you access any resource, that resource will include a list of links with information about what the user might want to do next. If a link doesn't appear in a response, the implication is that the user can't perform that action (due to permission issues or otherwise).
I'm creating a web app with Firebase on the back end where multiple users can access a feature, created by a root user.
The real-time db structure looks like this
project
project id
userID:userID of the user who created it
meta:other information about the project ...
team:
memberid1:{}
memberid2:{}
Until now, I've only allowed the root user to access the project. To do this, I've used the ref.orderByChild('userID').equalsTo(userID of user logged in) method of firebase js sdk to determine if the logged in user can access it because userID is a direct child of projectID.
But now, I want to allow multiple users to access a project. For this I've added a new child called team under which members can be added. But I can't use the aforementioned method to determine if a user who's logged in can access the project because the memberID is a grandchild of the project and hence orderByChild chained with equalTo won't work.
How could I do this with the DB structure as I stated above, and if it's not, how could I do this with a change in DB structure.
get project_id and team members of all projects and store in object with project id and member_id.Then, get project_id of corresponding to member id of logged in user and retrieve the project if project exists.
Yes we can definitely do that,the below code tries to explain that.
var uid = UserId of user logged in
ref.get().then(function(doc) {
if(doc.data().userID == uid || doc.data().team['memberid1] == uid || doc.data().team['memberid2'] == uid) {
\\ checks here whether user is authorized
}
});
One thing to note here is, if there are more than 2 members then this code may not be optimized