How can you specify a unique user in Firebase - firebase

I am trying to match each user with the respective advertising_id, vendor_id, user_id and user_pseudo_id.
Since forever I was using the user_pseudo_id as the trusted unique identifier since it is always present in the data that returned (other ids sometimes return as NULL).
But lately I have noticed that user_pseudo_id can be the same for multiple users (symptom is there are events of multiple devices with the same user_pseudo_id; with differrent vendor_id and advertising_id though)
I cannot use CONCAT of those 3 ids as a unique key since most of the time 1 of them would be NULL or BLANK
Do you guys have any ideas to handle this problem or should I just ignore it since it doesn't really accounts for that much compares to the total number of users?

Related

Firebase firestore unique values in multiple fields

I'm creating an application for generating documents with unique id, my issue is that the id needs to be in a specific format ( 00000/A/B) so I can't use firestore document's id's.
The problem is also that I have that id's in different places,
#1 case
users/{userID}/id = //UNIQUE ID HERE
#2 case
users/{userID}/members <= members is an array of objects where every member need a unique id
I was thinking about the separate collection of id's where I can check which one is taken but maybe is there a better way to ensure id is unique across the whole app?
What you're considering is pretty much the only way to guarantee uniqueness of a value across the database.
In a few more structured steps, it'd be:
Use that value as the document ID in an secondary collection. This collection purely exists to ensure uniqueness of the IDs.
Let the user claim it, typically by writing their UID into the document.
Use security rules to ensure a user can only write a document if it doesn't exist yet, and (if needed) only deleted when they own it.
The topic of unique values has been covered quite a few times before, although usually in the form of unique user names, so I recommend checking out:
Cloud Firestore: Enforcing Unique User Names
How to generate and guarantee unique values in firestore collection?
How to enforce Uniqueness in a Property of a document field in Google Cloud Firestore
Firestore unique index or unique constraint?
I want to make unique usernames in firebase/firestore

With all Firebase products, Is it possible to return a positive integer with out repeat

Same as SQL, you can add a new row with the primary key being auto incremental.
We need a counter where we can get unique values ​​even if we call them at the same time. (the result should be n and n+1)
Is it possible for all firebase products to create a counter that returns you a value that is never the same?
Eg.
It's possible to tell that user from firebase authentication is the first, second or third from a register (the sequence should never change) if it's so it would be great
A counter that gives you a number that never is the same even I and others request at the same time.
Main purpose
I want a 1-1 map, a positive integer (UInt32) to firebase account UID
eg. 1: aksd12391, 2: da1293nvs1dks, 4: 1is91jesoc
Using Transaction's Firestore (Concurrency)
It still returns the same not unique
Is it possible to create a counter that
returns you a value that is never the same?
Yes, you can use a numeric field in a Firestore document that you (transactionally) increment as explained here in the doc.
It's possible to tell that user from Firebase authentication is the
first, second or third from a register (the sequence should never
change)
Yes, you can assign a unique value (obtained as explained above) to a user, by, for example, saving a user profile in Firestore and assigning this value as a "functional" id.

Conditional insert in Dynamodb

I am creating a leave tracker app where I want to store the user ID along with the from date and to date. I am using Amazon's DynamoDB as the database, and the user enters a leave through a custom command.
Eg: apply-leave from-date to-date
I want to avoid duplicate entries in the database. For example, if a user has already applied for a leave between 06-10-2019 to 10-10-2019 and applies for a leave between the same dates again, they should get a message saying that this already exists and a new record should not be created for the same.
However, a user can apply for multiple leaves and two users can take a leave between the same dates.
I tried using a conditional statement as follows:
table.put_item(
Item={
'leave_id': leave_id,
'user_id': user_id,
'from_date': from_date,
'to_date': to_date,
},
ConditionExpression='attribute_not_exists(user_id) AND attribute_not_exists(from_date) AND attribute_not_exists(to_date)'
)
where leave_id is the partition key. However, this does not work and a new row is added every time, even if it is the same dates. I have looked through similar other questions, but haven't been able to understand how to get this configured correctly.
Any ideas on how I should go about this, or if there is a different design that I should follow?
If you are calling your code with the leave_id that doesn't yet exist in the table, the item will always be inserted. If you call your code with leave_id that does already exist in your table you should be getting An error occurred (ConditionalCheckFailedException) when calling the PutItem operation: The conditional request failed error message.
I have two suggestions:
If you don't want to change your table, you can create a secondary index with user_id as the partition key and then query the index for all the items where the given user has some from_date and to_date attributes.
Like this:
table.query(
IndexName='user_id-index',
KeyConditionExpression=Key('user_id').eq(user_id),
FilterExpression=Attr('from_date').exists() & Attr('from_date').exists()
)
Then you will need to check for overlapping leave requests, etc. (eg. leave request that starts before the one that is already in place finishes). After deciding that the leave request is a valid one you will call put_item.
Another suggestion and probably a better one would be to create a composite primary key on your table with user_id as a partition key and leave_id as a sort key. That way you could execute a query for all leave requests from a particular user without the need to create a secondary index.

Firebase query for bi-directional link

I'm designing a chat app much like Facebook Messenger. My two current root nodes are chats and users. A user has an associated list of chats users/user/chats, and the chats are added by autoID in the chats node chats/a151jl1j6. That node stores information such as a list of the messages, time of the last message, if someone is typing, etc.
What I'm struggling with is where to make the definition of which two users are in the chat. Originally, I put a reference to the other user as the value of the chatId key in the users/user/chats node, but I thought that was a bad idea incase I ever wanted group chats.
What seems more logical is to have a chats/chat/members node in which I define userId: true, user2id: true. My issue with this is how to efficiently query it. For example, if the user is going to create a new chat with a user, we want to check if a chat already exists between them. I'm not sure how to do the query of "Find chat where members contains currentUserId and friendUserId" or if this is an efficient denormalized way of doing things.
Any hints?
Although the idea of having ids in the format id1---||---id2 definitely gets the job done, it may not scale if you expect to have large groups and you have to account for id2---||---id1 comparisons which also gets more complicated when you have more people in a conversation. You should go with that if you don't need to worry about large groups.
I'd actually go with using the autoId chats/a151jl1j6 since you get it for free. The recommended way to structure the data is to make the autoId the key in the other nodes with related child objects. So chats/a151jl1j6 would contain the conversation metadata, members/a151jl1j6 would contain the members in that conversation, messages/a151jl1j6 would contain the messages and so on.
"chats":{
"a151jl1j6":{}}
"members":{
"a151jl1j6":{
"user1": true,
"user2": true
}
}
"messages":{
"a151jl1j6":{}}
The part where this gets is little "inefficient" is the querying for conversations that include both user1 and user2. The recommended way is to create an index of conversations for each user and then query the members data.
"user1":{
"chats":{
"a151jl1j6":true
}
}
This is a trade-off when it comes to querying relationships with a flattened data structure. The queries are fast since you are only dealing with a subset of the data, but you end up with a lot of duplicate data that need to be accounted for when you are modifying/deleting i.e. when the user leaves the chat conversation, you have to update multiple structures.
Reference: https://firebase.google.com/docs/database/ios/structure-data#flatten_data_structures
I remember I had similar issue some time ago. The way how I solved it:
user 1 has an unique ID id1
user 2 has an unique ID id2
Instead of adding a new chat by autoId chats/a151jl1j6 the ID of the chat was id1---||---id2 (superoriginal human-readable delimeter)
(which is exactly what you've originally suggested)
Originally, I put a reference to the other user as the value of the chatId key in the users/user/chats node, but I thought that was a bad idea in case I ever wanted group chats.
There is a saying: https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it
There might a limitation of how many userIDs can live in the path - you can always hash the value...

Permission based on one column - secure?

I am developing an early version of my site and before I create the production version, I'd like people's opinions on whether I'm going about things the right way. The main objective is to allow users to share playlists. I have the User table (ASP.NET Membership), Playlist table and a permission table. I'd like a user to create a playlist and grant/deny access to it for a given user. My approach to this is to have the permission table contain a "pStatus" column where 0/null = deny, 1 = read.
When a user requests permission to access a playlist, the creator chooses the pStatus enumeration. The column is then changed accordingly for the recipient. When accessing the recipient's profile page, a scan of the column is done to check all playlists the recipient has access to and the relevant playlists are displayed.
Is this an efficient and secure way of doing things? Or is relying on one column not enough?
(nb - playlists can be considered to be similar to Facebook groups)
Thanks for any advice
I would use some sort of bitmask in the n-m relation table I'm guessing is in between User and PlayList (i.e. a table named UserPlaylist, because 1 user can have access to more than 1 playlist and vice versa 1 playlist can be accessed by more than 1 user).
If you define the needed permission levels up front (i.e. 0 = no access, 1 = read, 2 = write, etc.), you can just add a column to the UserPlayList table, that represents the access level.
So the UserPlaylist table will have 2 foreign key columns of which the combination should be unique (i.e. define the primary key to be the 2 foreign key columns) and a column that holds the level of access in the form of a bit / integer.
So Permission has foreign keys to User and Playlist. Is there any reason for the third column specifying permission level? It sounds like it should be: If a row exists in Permission, the user is allowed to access the playlist.
Otherwise, that sounds good to me.

Resources