How to implement chat on deepstream.io? - deepstream.io

I'm trying to implement a real chat using deepstream.io.
Online many tutorials do deal with one single chat room that's shared between users, but the problem with this is, if one user deletes a message then its deleted on all users. In normal chat apps, every user has their own inbox, when a user posts a message its duplicated in the sender and receiver's inbox.
So I came up with this.
Use one global listener that listens to all messages being sent, then write those messages to database. Here it means I'm using event listeners. The problem with this method is scaling, because only one server keeps listening and handling all messages, an even bigger problem is if the server listening is down that means the messages don't get persisted.
Use deepstream list and records.
This one becomes complicated very fast, I have to use two lists? my list and the recipient list, subscribe to mine for any changes, and when I write a message it means I have to write to two lists the same message. This also means, I have to access two inboxes all on the client side, if the last message is changed I have to update two records as well. So I allow only writing on the recipient list but not delete because that list isn't mine. I don't know about this but can it fail?
Maybe there's something I'm missing. Has anyone successfully implemented a complete chat app with inboxes, and private messaging using deepstream.io?

The delete requirement definitely makes this a bit trickier because you're now talking about mirroring different data sets between users, however there are a few solutions.
(Using Lists and Records) If your chats are only ever 1 to 1, when a user deletes a message you set a flag on that record indicating the user has deleted it. Then with your valve permissions you don't allow users to see a message if they have deleted it. This will require a bit of application logic, however it's quite a clean approach. Your Valve permissions may look like something as follows
chat/$userA-$userB:
read: data.deletedBy !== user.id && (user.id === userA || user.id === userB)
You could also delete the record from the list, however you then end up with the situation you described before.

Related

Are login/register commands or queries in CQRS

So for the login, since it doesn't really make anything new in the database but rather just returns if we've logged in, and possibly some user data, should it be a command or query?
And as for the register, since it creates a new user, should it be a command then? What if i want to return the users data or a jwt?
Should i run my commands and once the client receives a response run a query right after them?
As with most design related questions, I’d answer this one with ‘it depends’. I have seen both solutions implemented in different situations.
The main question you’d need to ask is whether you consider a user logging in as a state change of the system or not. Note that whether it changes state in de database isn’t relevant. The system is more than the database.
Log in as a command
For some systems, it’s important to know which users had been logged in and when, from where, etc. One example I had seen was a medical system that needed to record which doctor logged in when and where, and which medical records had been accessed. Also, logging in on one machine would stop tbe session on another. A reliable trace of these actions was essential to the application. As such, log in was implemented as a command which generated events that were stored in the Event Store. Projections kept the current logged in state for each user.
Log in as a query
Most systems I have seen, however, simple beed to know whether any given credentials can ve mapped to a user account. If that is the case, a token is generated containing the ‘proof’ of authentication. The system itself doesn’t really care who is logged in. It’s just that each request needs to be validated by checking the ‘proof’. In this case, logging in is a query.

Auth0 database and social connections, unique email addresses

Maybe I am missing something here, or this is a flaw in Auth0? I'll give an example of my issue:
Let's say I have my Default App (client), hooked up to that I have Username-Password-Authentication (database connection) and google-oauth2 (social connection).
A user comes to my site, signs up via google-oauth2 (social connection) using joe#gmail.com. Once complete, he gets added to my users in Auth0, all great.
A few months later, Joe comes back to my site, and being a busy guy, he forgets he signed up to my site before. This time, he decides to sign up using my custom Email and Password form, that will add the user to the Username-Password-Authentication (database connection). so he signs up there using joe#gmail.com again, and everything goes well, he is now listed in my user's section in my Auth0 dashboard.
This is the problem, I now have two joe#gmail.com accounts, one with google-outh2 and one with Username-Password-Authentication. I really can't have this, I need a unique email address, regardless of the ID Auth0 supplies.
Does anyone know how I can make email address in my user section 100% unique? I'd think a rule would do this, but it appears rules only apply AFTER a user has been registered, so I can't run a rule before adding?
the only way I can see doing this right now is make my own checks and delete via the management API, but that is a really long and messy way to do it I feel.
Any help will be appreciated here!
Thanks!
Auth0's default behavior is to create a new account in the database for every unique entry. Since the user created using Google has a unique id (based on google-oauth2), and the user created using the sign-up form has a unique id - they will technically be considered two separate accounts. In order to resolve this disparity, you can establish a means with which the account data can be merged. In the documentation linked provided above, there are examples of three possible ways of doing this:
Automatic Linking - which involves creating a specific rule to merge users based on matching emails
User-Initiated Linking - which involves providing a UI for users to opt into merging users with matching emails
Suggested Account Linking - which involves setting up a rule that is linked into the UI
One important thing to consider is that the data returned from different social identity providers may not be normalized the way that data is normalized onto the Username-Password-Database. For example, while auth0's default for emails is to lowercase the information, google-oauth2 may return emails as Uppercased - creating the potential for non-matching emails when checks are made using strict equality
The option you are looking for is called account linking.
You can find more info at https://auth0.com/docs/link-accounts

SignalR: Get clients list for PersistentConnection

I searched google, SignalR wiki and SignalR code itself (for example, Broadcast function, Signaler and more), and found nothing.
I wrote ClientIDFactory and successfuly set ClientID to UserID.
It works, but now user cannot connect from more than one browser/tab.
I modified the function and added random string to the UserID. It works.
Now I need to find a way to get all connections for user(s), to send specific message to specific UserID.
I think about looping around client list, and find the UserID by string.split(), but other ways may be usefull.
I am not using Hub. only PersistentConnection.
Thanks,
I think your approach is not right hence this has surfaced. You have connect and disconnect method on server side to hook into. On Connection you need to persist connection with some meta data and then even if server restarts you can check meta data for unique user or unique client and reconnect them with new ID.
For example
If you are buying an item from mobile and you are not logged in (no meta data to relate to user) and you place 2 items in your basket. When you go on your desktop you wont see those two items in basket because server cannot relate to you as same user coming from same machine.
If you are logged in (meta data like email or username attached to current connection ID) and you browse from mobile and add 2 items in basket. When you login to your desktop (the new Connection ID can then be linked with same meta data email or userid) and then you can tell that its same user. If you then need to send a message to that user you have to send it to two client IDs which you can do by grouping them or sending it to two IDs.
If client lost connection ID it should be disconnected and on new connection it will have new connection ID so you should be thinking about mapping them.
If I connect with 7 IDs from 7 different mobiles notification would be sent to all 7 as long as your system knows that they are all intended recipient of this notifications. Implementation of persisting this knowledge is not part of signalR and so you have to implement it yourself.

AppEngine Channel API - Best way to check if a channel is still open (server side)

I have built a social network/dating type application on the AppEngine and am currently in the process of adding a chat built on top of the Channel API. However, the problem that I have is that users may reload or navigate to new pages while the chat is going on (as they can in Facebook). This means that the server doesn't easily know if it should generate a new channel ID token for a given client, or if a given client has already been assigned a channel token.
It would be extremely useful if there were a way to check (server side) if a particular client already has a channel open. For example, if I assign a client "Jack" a channel ID of "Jack-Jan-21-2010", then I would like to be able to check on the server side if there is already a channel open associated with the ID "Jack-Jan-21-2010". This can be (sort of) tracked on the client side by watching for an onerror() and onclose() callback, but I can't see anything server-side that allows me to just check if a channel associated with a given ID is already open.
Does anyone know an intelligent way to check (server side) if a channel has already been opened, while using the AppEngine Channel API?
Part 1: Solving your problem
See Part 2 below if you really need to track client connections, but I'm not sure from your question if what you're asking for will solve your problem.
Let me see if I can echo your problem back: you're writing a chat app, but it's for a site which isn't fully AJAX (in the way that, say, gmail is); the site contains page navigation where you may need to re-set up your channel after the user clicks on a link to another page. When the user navigates, the new page is rendered, and you want to avoid getting a new token at that point; you want to reuse the existing token and channel with the same client-id.
If that's correct, I have two alternate solutions, one easy but with not-great user experience, one trickier but with a much smoother end result.
Preserve the token in a cookie. When you re-render your page, just use the token from the cookie instead of calling channel.create_channel again. When the token expires you'll get an onerror callback just like if the user had stayed on the original page; at this point, call channel.create_channel again. The problem with this is that re-connection can be slow (up to 10 seconds or more in bad cases) because of the nature of Comet connections.
Wrap your entire site that's not chat-related in an iframe. Put your channel creation code and UI in the outer iframe. This way you don't have to re-connect every time the user navigates. This avoids the downtime on navigation. Note that orkut uses this technique, with floating divs, as a small amount of Firebug investigation will reveal.
Part 2: Your feature request
If it turns out I'm misunderstanding and you really do need to track client connections:
There's not a built-in way to check if a client is connected to a channel identified by a client-id now.
However, I am working right now on adding "presence" (in the chat sense) so that your app can register to get a post when a client connects to or disconnects from a channel created with a given client id. You also might be able to "probe" presence, to query whether a given client id is connected or not (still working on the details of this part).
Note that this won't be token-based, but rather client-id based.
I don't have a definite release date for this yet but as I said I'm actively working on it right now.
In the meantime, you could use a heartbeat HTTP request from your client back to your app that says, "hey, I'm still here" every minute or so. You'll need to have some sort of task that runs every, say, 2 minutes and marks any clients that haven't checked in as inactive, and you'll need to store this data someplace.

How to track & store email replies?

Currently on our system, when a user contacts us, we reply via our admin panel. The user is then sent an email containing our message and the other messages in the conversation.
Then the user has to click on 'Reply to this message' which opens up our website, with a contact enquiry form, and submits the message to the conversation (using a QueryString to tell which conversation it belongs to).
However, a lot of users like to simply reply to the email sent to them.
How can I track their reply and automatically add this to the same conversation?
We're currently using ASP.NET 3.5, IIS6 & SQL Server 2005, however will be upgrading to ASP.NET 4.0, IIS7 & SQL Server 2008
Thanks,
Curt
It's not a full code solution (but hey, that's not what this place is for anyway), but this is a general idea:
Specify a reply-to header in the messages you send (or simply use the from address). Then set up a script that periodically reads the emails send to that address and inserts them into your database (to be viewed). In order to get the correct threads, you can use the in-reply-to header in the message sent to you. I don't know by heart how to find the message-id of a mail you sent, but a little research on your part should reveal that. (if worst comes to worst, you can always BCC yourself the message and read it from there, but there should be easier ways).
Note that some people (most notably GMail) refuse to use in-reply-to headers because of how people use email (though I don't think it would be much of a problem in the case you are describing) and use topics to create threads instead. This may be an easier solution, though it may be less reliable in your case.