How to use Session in SignalR connect - signalr

In my database a user has some area permissions.
What I want to do is to add this areas into Groups of SignalR.
So, when user sign in, I get this groups from database and save in Session["groups"] and when user connect to signalR, I use this session to add in Groups.
Something like this:
public Task Connect()
{
var groups = (string[])Session["groups"];
foreach (var group in groups)
{
Groups.Add(Context.ConnectionId, group);
}
}
How can I do this or something like?

As mentioned here SignalR Hubs - Managing groups
You can add connections to groups and send messages to particular groups. Groups are not persisted on the server so applications are responsible for keeping track of what connections are in what groups so things like group count can be achieved.
That means that you have to provide your own structure such as a Dictionary to hold your data.
For example, a Dictionary to hold group name as the key and List of areas as values (or the other way around if it suits you best).
So for each new area of your user, first update this Dictionary and then subscribe the user to the groups that were changed.
Groups.Add(Context.ConnectionId, group);
Nevertheless take a look at the link above and also here Topic based pub sub design patern. Do not hesitate because of the WCF on the title. Get a closer look on the way he implements the Filter class

Related

MongoDB Realm - Block data leaks

I am in the stage of setting up MongoDB Realm sync with Schemas but I have a question regarding data breaches.
My schemas looks like this:
User {
id
name
groups[] (ids)
}
Group {
id
name
members[] (users - Inverse Relationship)
}
I would like the user to login and receive their user data which includes the groups they are members of. How can I define the sync rules (or another way?) to stop anyone reverse engineering my app code and change the partition (group ID) and get access to other groups?

How to manage groups in SignalR core? (joining/leaving from all)

I have some questions about SignalR.
An app scenario: An user can join/leave to many groups (NxN). But
those groups can be changed with a new request. So, how to remove an
user from all joined groups and add him to new list of groups? (Such
as: in first request i join A,B,C groups and with second request i
want to be in only groupS X,Z -i'm not listening a,b,c groups anymore-).
How to check a group name if it's already exists?
How to remove a group if it has no users/members in it? (garbage collector)
Hope someone helps me here!
(Signalr core: 2.2)
SignalR don't provide you the list of users that are in groups, how many groups there are and their names. So the logic that you need to implement is create for example a Dictionary so you can add there the name of your group and the users that are associated to that group. So when a request comes to change user from group A to group B you can do:
Lookup in what groups the user is.
Remove the user from the group.
Create the new group and add it to your Dictionary.
Add the user to the new group.
I believe this is a good aproach if you have one SignalR app/host because if you will have many instances of your signalR app, you can not access to the Dictionary to see if there is a user in some group in some other instance.

.net core signalR, how to know the group name when a user leaves the group

I am working on a chat application.
As I understood, a single connection can join multiple groups.
And it works for me.
But when the user leaves one group, I will have to populate the existing user's name in that group.
so I think if I somehow know what is the group name that user left, I can remove that entry from the database.
public override async Task OnDisconnectedAsync(Exception exception){}
I assume this is the place where I have to do the thing.
BUT, how would I know the group name here?? Any ideas?

Securing specific Document fields in Firestore

I'm trying to create a simple system that allows users to create an account with info that they provided. Right now, I store all the data in a Collection users which has some Documents that represents users.
I'd like to keep some sensitive data of the user, such as the email address and phone number, private. In Firebase Database I would've created something like this:
users: {
uid: {
public_info:...
private_info:...
}
}
Protecting the data in here is pretty straight forward. I would simply write different rule sets for the private_info and public_info.
How would something like this be achieved in Firestore?
Use different top-level collections for user public and private data, and set their rules appropriately.
Depending on the use case you have two reasonably useful options:
Have a top level collection (public) with a sub collection called something like "private_data" (private) and grant access accordingly.
--OR--
Have a top level collection (private) with a sub collection called something like "public_data" (public) and grand access accordingly.

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...

Resources