Getting uid after createUser() - firebase

With iOS/MacOS is there a way to retrieve the uid immediately after createUser?
Our app allows an Admin user to create other user accounts (email/password authentication) and also stores some other info about the created user in our Firebase with the uid as the key.
One solution is when the admin creates the user (createUser), it's followed by authenticating the user, grabbing the uid from FAuthData that's returned and then create the key/value pair in our Firebase with the user data. Then that account is unauth'd.
In doing a Google search, there were a couple of references to something like this
-(void)createUser:(NSString *)email password:(NSString *)password withCompletionBlock(NSError *error, User *user) {block}
where it appears a user (or FAuthData?) was returned.
If no, what is the best practice to get the just-created uid? Is this a feature that is upcoming?
2/22/2016 update
For completeness, soon after I asked this question, Firebase was updated with a method that created the user and returns the uid at the time of creation:
createUser:password:withValueCompletionBlock:
- (void)createUser:(NSString *)email password:(NSString *)password
withValueCompletionBlock:(void ( ^ ) ( NSError *error, NSDictionary *result ))
The result dictionary contains newly-created user attributes, including uid.

Related

How do I implement a follower system with private accounts in Firebase?

I'm building an an app in Firebase with a user feature and I need to implement a system to allow:
A user to follow another user
A user to see a list of the users they're following
A user to set their profile as private so that some of their data is only visible to the people following them
A user to be able to send a follow request to a user with a private profile
A user with a private profile to be able to accept/reject follow requests
So far I've made a Firestore collection at the root called users. When a user signs up with Firebase Auth, a document is made in users with the following structure:
user (document)
username: stringaccountIsPrivate: boolean
userData (collection)
userData (document)
where all the data that would be hidden if the account were private is in the userData document.
I'm not sure how I could implement the system to fulfill my requirements from here so that I could use Firestore rules to only allow followers of a private account to view that account's userData. I would appreciate it if anyone could suggest an appropriate data structure and an outline of how to write rules for this.
For this kind of situation, you must maintain two sources of truth, one for the creator and one for the user. this is done with an array of strings in both that have the user_uid and any additional information concatenated.
The goal is to have an array of CSV-like values of which you can split and render within your app.
create a concat string: entry = [user.uid, user.name, user.url].join(';');
return string to object: entry.split(';');
Doing the following ensures that only a unique entry exists
db.doc("user/user_id/userData/followers").set({ followers: Firestore.FieldValue.ArrayUnion(entry)}, {merge: true});
This is only a rough example and some backend logic will be needed to scale large - but with this, you have a theoretical limit of 200k entries depending on how much data you want to store in the string.
Additional logic would involve cloud functions reading and writing when a request to follow has been created which handles a counter that creates new documents as needed and ensure's that the counter is updated to prevent overflow since Security Rules can't do any recursive logic or manipulate the request directly.

Save way to create a Firestore document

I made a game with JavaScript in which the user takes a specific amount of time to complete it. Then I want to create a document in a collection named scores on Firestone with that time. My problem is that the user can create an infinite amount of documents with a random time by simply copy & pasting the code and entering their own values. Is there a way that the user can only create once a document with the correct time at the end of the game? Here is the code that I used:
db.collection('score').add({
time: 122,
});
You have two requirements I think:
The user should only be able to create one document.
The time in the document must be the current time at the end of the game.
Allow only one document per user
The first one is easiest to do by using Firebase Authentication to sign the user in, so that they have an identity. If you don't want the user to enter any credentials, you can sign them in using anonymous authentication.
No matter how you sign them in, this gives them a unique UID (user identifier), which you can then use as the document ID:
let uid = firebase.auth().currentUser.uid;
db.collection('score').doc(uid).set({
time: 122,
});
So instead of calling add() (which generates a new document each time you call it), we create a document with the user's UID as its name. That way the user will always be writing to the same document.
You can then enforce that the user can only write their own document with Firebase's server-side security rules. See for an example of this, the documentation on content-owner only access.
Ensure the time can't be spoofed
To prevent the user from writing just any value they wish into the database, we can use Firestore's built-in FieldValue.serverTimestamp marker value. When you use this in your code, the Firestore server automatically writes in the current value from the server:
let uid = firebase.auth().currentUser.uid;
db.collection('score').doc(uid).set({
time: firebase.firestore.FieldValue.serverTimestamp(),
});
Here too, you can then use Firebase's server-side security rules to ensure that a malicious user can't pass their own value. To do that, compare the value that is being written (request.data.time) with the built-in variable for the current time (request.time).

How can i check username availability in my flutter firebase app

I am trying to check if a username is already taken in my flutter and firebase app, but I am facing some problems.
I am able to query the user's collection and compare a name string saved in the input of the text form with names already in the database, which works perfectly well. But my problem is when a user takes a name and that same user tries to save his profile without changing his name, he gets the message username is already taken, meaning he can't save his profile cause he has already taken his own name.
I want a solution where a user can save his profile if he or she hasn't modified his or her username without going through the username is already taken process. I don't know if it's possible to add an if statement to check if the current user name is equal to the username in the text field? or help with any solution that works.
please these are my codes below
//checks fields of user collection and compares the
//string _username with the userName of each user.
final QuerySnapshot result = await Firestore.instance
.collection('users')
.where('userName', isEqualTo: _userName)
.getDocuments();
//converts results to a list of documents
final List<DocumentSnapshot> documents =
result.documents;
//checks the length of the document to see if its
//greater than 0 which means the username has already been taken
the name
if (documents.length > 0) {
print(_userName + ' is already taken choose
another name');
}else{
print(_userName + ' are you sure you want to use
this name');
}
I think a solution would to only check to see if this username is taken if the user changes his username! Therefore you would not have to worry if the user with the taken username is just saving his profile without changing his username.
yes if you are in firestore as backend...you can not show query stream in registration page for username suggestions for availability bcoz u hav to set firestore rules insecure and allow unauthorised users to read write your database...so better to push a new page after that registration page where you can place field for username in this case you are already registered and logged in so firestore security rule will not invade....
Happy coding :)

How to write to a document and read the id of it within a single transaction in Firestore?

I am doing the user authentication where I have this case:
Read from vendor_type document and if it returns null(doesn't exist) then continue the transaction,
Create new user using .auth().createUserWithEmailAndPassword(email,password),
Read the new users ID,
Write to vendor_type document some of the new user's detail such as name, surname, userId -->> userId is the problem, how can I create a user and get the ID within a single transaction, can I even do that? ,
Take the newly created ID of the user, and create a new vendor document with that ID.
So far I don't have any code to post because I don't know if this is even gonna work so I didn't start. If you have any idea how to implement this, please let me know. The main issue is getting the user ID while still in the transaction.
At the time of writing, it is not possible to combine in one transaction the creation of a user through the createUserWithEmailAndPassword() method from the Auth service AND a write to the Firestore service.
They are two different services offered by Firestore and therefore you cannot combined calls to these two different services in one transaction.

Dynamic Group Security in Firebase Storage

I've reviewed the documentation for Group Security for Firebase Storage where it suggests to use custom tokens or including group information in file metadata, however, when a user leaves a group, I don't ideally want to be updating the metadata in every file or having to create a new folder and update the group token information.
If this were the Realtime Database, I'd check to see if the user was still a group member. Is there a more elegant solution along these lines that I can explore?
Many thanks
yeah with custom tokens you can associate additional attributes with the user. The trick is when you create custom token for a given user id, you can add additional claims and use them to evaluate the access rules. In your case you can add the group id to which the user belongs as additional claim when the token is created on your server using which the user logs-in from the client app. So whenever the user leaves your group, his group id association is removed and hence when you recreate the token for that user, you will no more associate the group id in additional claims.
Sample Example
public static String createCustomToken(String userId, Map<String, Object> additionalClaims) {
FirebaseOptions options = new FirebaseOptions.Builder()
.setServiceAccount(new FileInputStream(FIREBASE_ACCESS_FILE)).build();
FirebaseApp.initializeApp(options);
Task<String> customToken = FirebaseAuth.getInstance().createCustomToken(userId, additionalClaims);
return customToken.getResult().toString();
}

Resources