I'm currently running into an issue creating or updating a large amount of users (200+) at once. Here's the issues of found so far:
Existing solution - Keeping users as Users, I must fetch all users with my list of email addresses, saveAll() changes to users with the existing email addresses and then signUp() users who do not exist. The problem here is running into the request limit.
Problematic solution - I believe I could use a saveAll() method if the users were not Users, but then I lose the ability to store passwords and use the signIn() method associated with it
Problematic solution - User a background job: I haven't tried this but, "Jobs that are initiated after the maximum concurrent limit has been reached will be terminated immediately" scares me a bit as well.
The reason I need this is because I need a company to be able to upload their users for use in our application. The users have information stored about them and can log in to check the information, so I would really like being able to use the User class.
Another option would be to pay to up the request limit, but if we jump to creating/updating 2000+ users, we'll be right back to the same scenario...
Related
I have a group chat app. Each chat document has a node called
chatUsers:[1,2,3,4,5]
where 1-5 is a user Id on that node.
I need to pull all chats where I am a user, so I use the array-contains operator. My issue is there is also another node called archivedChat. That node tells if I archived the chat.
ie:
archivedChat:[1,2]
meaning users 1 and 2 have archived this chat. I want to get all chats where I am a user and I have not archived, and then all chats I am a user and have archived.
firebase prevents using these two operators together, and I understand I can filter on the front end, but I'd need all records retrieved that. I could have 1000 chat rooms/documents, so I do not want to query the entire collection, I'd much much prefer doing 2 separate queries. Here is where I am at:
query(
roomsRef,
where(USERS_PATH, 'array-contains', currentUserId),
where(ARCHIVE_USERS_FIELD, 'not-in', [[currentUserId]]),
orderBy(LAST_UPDATED_FIELD, 'desc'),
limit(roomsPerPage),
startAfter(lastRoom)
I can think of no way to do this. Since the chat is the same whether it is archived or not, and my archived flag just shows all archived chats in a different area and effects how I display it, I really do not want to move it into another collection....
Any help?
I'd recommend adding a third field that essentially combines the information from the other user lists. If you only want to show the document for users that are in the USERS_PATH and are not in ARCHIVE_USERS_FIELD, add a field (say SHOW_USERS) that contains just the UIDs of those users.
This type of data duplication is quite common when using NoSQL databases, where you often have to model/augment your data to fit with the specific use-cases you have.
After learning the limitations, i think i am going to go to mongodb cloud and ditch firestore.
Firestore is very good, but if you want complex queries ie(users are part of teams, and we want both team chats to be pulled along with user chats, team chats a user is not on, user chats archived, and team
chats archived from a users view, there is no great way to query.
Lastly if i could have 1000 team
Chats all with listeners on the room user online status’s, etc i can easily exceed quota limits.
Mongodb requires a server layer but there are no server limits, and better query capabilities.
Much more complex to build as subscribing to documents has to be pushed via sockets instead of a very clean front-end sdk that firestore has.
Each has their perks, but a large scale chat app with 1000+ rooms and complex querying feels like forcing a square peg through a round hole here:(
I'm trying to build an app that works like a classic videogame, with some challenges that the user must complete in order to advance. Based on how the user solves the puzzles, he/she will gain XP points, badges etc. The user can quit the app and come back later, with an authentication system.
I'm planning to use Firebase Auth for authentication and Firestore for the database. It's the first time I use Firebase services in (somewhat) production environments, but I've been experimenting a lot with their services lately.
Firestore will be used to store a set of data for every user, but mainly his/her score. I'm somehow familiar with Security Rules in Firestore, and know how to make sure that only authenticated users can write to the db, perform data validation before giving write permissions etc.
However, there's one problem I cannot come up with: how can I be sure that the (authenticated) user will not use the browser console, or a custom API call to update his/her points and write them to the DB? Like in the first part of this video: https://www.youtube.com/watch?v=b7PUm7LmAOw&t
To sum up: my expected result would be that the (authenticated) user could update his/her score on my Firestore DB only by using the UI (i.e. solving challenges) and not by making a direct call to the DB. I thought of some other solutions (e.g. sending only user response - like answers to a quiz - to the DB and then updating the scores server-side with Cloud Functions), but it seems to me that I'm over-complicating a simple issue.
I've watched and read a good amount of guides on security in Firestore: they do a good job explaining how to secure an app from un-authenticated hackers, but I am yet to find a guide on how to defend the app against unwanted behaviour from authenticated users.
Thank you in advance for any guidance on this, deeply appreciate it. Stay safe :)
UPDATE: looks like the only way to manage data flow to the DB when you can't "trust" the authenticated user is using Cloud Functions. Thanks!
Listen to score, points, badges in real time using Firestore. You may set the security rules to these fields as READ ONLY for an authenticated user, setting write permission for a service user (that will be used in your cloud functions).
Send Quiz answers using a cloud function, that will be processed using your service authenticated user (with write permissions to the collections).
Thus, your cloud function may be responsible for checking answers and preventing user abuse from console and other methods.
In the firebase API
https://firebase.google.com/docs/auth/web/manage-users
we can delete users, but how could we prevent users from simply registering again, in the GUI for firebase we have the option to disable users , how could we do this in the program, for example if we are building a admin panel that checks posts for a listing site that have been reported, and we want to disable the creator or the reporter for spamming as part of availiable actions.
Thanks.
I develop in react if that changes the answer.
To prevent the user from re-registering, you should disable account instead of deleting it. This will prevent the user from signing in again, and from refreshing their ID token. If you want to do this programmatically, have a look at updating a user with the Admin SDKs. For example, in Node.js it'd be:
admin.auth().updateUser(uid, { disabled: true })
Keep in mind however that even after disabling the account, their existing ID token will remain valid until it expires (typically within an hour), and cannot be revoked. If you want to prevent them from posting in the meantime, you'll also want to keep a list of blacklisted/blocked UIDs somewhere, and check against that list before allowing them to write/access the data.
You will not be able to programmatically disable a user from the frontend of your app. You will need a backend, and use the Firebase Admin SDK to update the user account to become disabled. The API is updateUser.
Well they can always register again (in case the website is public/ not invite-only), with completely different credentials.
You can do a matching of the new data and existing blocked users, and if it matches above a threshold, flag them.
And you can improve your reporting, the faster you detect a user who should be blocked, the better.
Can't say I'm super familiar with Firebase but ill try and help (can't hurt).
Have you tried to blacklist the IP of the user in question?
Hope I helped :)
Have a good day!
I need to make an authentication system for an express app I'm building. The client asked to have a password system that uses just a 4-digit pin. I have the code setup to save and hash the pin with the rest of the user info when creating a new user and the project is just an in-house server so it doesn't need to handle a ton of users.
My problem is signing the user back in. I'm using bycrypt to hash the password, but bycrypt generates a completely new hash for identical strings.
What I'm having trouble doing is fetching the user by doing a WHERE hash=hash SQL search. But that's not working because the hash is different every time even when the passwords are identical.
I could get all the users and iterate over all of them and use bycrypt's .compare method. But that won't work in the long run as the amount of users grows, and bycrypt is build to take a long time on cpu's to help prevent brute-force attacks.
I could also build my own hashing function. However, that would make it so I have to store a salt with each user to make each password unique. Then that brings up the same problem of not having the same hash for identical strings.
I know this is vague but I need some help thinking up a way to get the user by fetching it using the hashed password.
Just store the PIN as plain text. Using a hashing function on a 4 digit PIN does nothing but provide a false sense of security. Even an intentionally slow hashing function is easy to brute force if there are only 10,000 possible inputs.
What I'm having trouble doing is fetching the user by doing a WHERE hash=hash SQL search
Are you saying that you don't even know who the person claims to be, but are using the 4 digit pin as both the claim and the proof? It sounds like you building a system with only a pretense of security.
I am currently in a situation as follows -
I am currently hosting a private webapp, which involves the sending of AJAX calls to the database server and displaying the results. (REST Architecture)
Users can query the database by toggling various buttons, which correspond to a specific query that performs the above operation.
Users have access to the entire database (product feature). However, we only allow the retrieval of a small portion of the database in a single call.
However, I do not want the user to be a able to create a bot that is able to recreate the entire database in a short period of time. At the moment, a user could easily do so by duplicating the HTTP request (access to JS script/packet analyzer).
I have considered the following solutions -
Bot detection algorithms
Captcha
iframe
disabling the ability to read source code/JS files with a custom browser
I would like to find out if any of these solutions are feasible, or if there are any better alternatives/architecture available. I just want to prevent the scrapping of the database.
Please help! Thank you!