Sails.js simple private messaging (pub/sub and models) - javascript

My Goal:
Create a private messaging platform using Sails.js with the simplest code possible
Assumptions of Best Practices:
Use Sails.js Webockets for realtime notifications
Use Sails.js PubSub for DB use with websockets
Use Sails.js .watch() to get messages
My Questions:
Can I have a socket watch only certain new models (e.g. find where userid matches sender or recipient id) OR do I need to set up rooms? Selective watching seems much easier, but the documentation doesn't seem to support it.
If any of my above assumptions or questions are not the best way to realize my goal, then what is the simplest way to implement private messaging using Sails?
What I've Tried:
Subscribing and watching a socket
Reading the Sails.js documentation
Looking at the sailsChat example (uses rooms)
Searching StackOverflow and Google for sails chat examples

The simplest way I guess it is using the socket.io implemented in sails, if I remember correctly it is simply called socket.
All controllers can be called with socket.io (client side) IIRC.
The approach that I took is to create a model called messages, and then simply create few endpoints for the messages. If you want to use the models (pub/sub) it is possible to subscribe just to the ones you want. you can subscribe every single user to just a single Model, even if you have plenty of them.
What I used to do is do it manually, when I receive one message, i would emit it to the right client straight away. But if you want to write less code probably you simply have to subscribe the users to your model Model.subscribe()( http://sailsjs.org/documentation/reference/web-sockets/resourceful-pub-sub/subscribe )
so when a message is added to the Database then you can send it to whoever you need to.
Here's another example of a chat built on top of sails.js: https://github.com/asm-products/boxychat-old

Related

Detecting where the model is used between c # and react

I create app using C# RestApi as backend and React as frontend.
I would like to ask you whether you inventory the use of backend models in the front.
In VS (C#) I can use F12 to detect reference. I have no idea how to do this in REST where JS does not need to recreate the class.
The backend developer may not be able to access the frontend code. Do you have any practice on how to record the use of the model on the REST/React so that the developer can quickly see if he can change the appearance of the backend model class.
Well, there is no strict connection between models defined in the backend and frontend in this case.
The connection is just made when a client calls an endpoint on a server.
The most common practice is to use DTO as returned data(Data Transfer Object) with all properties which you need on the front, not models.
So on the frontend, you create the same class as DTO on the backend and you just use some libs to support the process of mapping like the automapper.
In this case detection of using models needs to be found by URL.

Best practice for node - mongo - angular

I have an app I am designing using node/mongo/angular, what I am not getting is how is the best way to get my data from mongo into my pages? I can use node, and thru my routes send back data from mongo with my template(hogan in this case), and bind using mustachejs. That works fine for most things. I have one screen that has a decent amount of drop down lists, to bind them for an edit scenario now seems a challenge. I would like to get them bound to an angular model and go about it that way. Is it better to get the data thru the route in node, then use something like ng-init and get it into angular? Or would I be better off not getting the data thru the route in node, and then using angular to perform a "get" request and bind that way?
From the documentation of ng-init, more precisely from the red warning alert at the top of the page...:
The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
So no, do not use ng-init. While that can be a good strategy for lazy migrations from regular applications to single page applications, it's a bad idea from an architectural point of view.
Most importantly, you lose two things:
An API. The benefit of SPAs is that you have an API and that you're constantly developing and maintaining it, even before it has external users
A clean separation of concerns. Views are strictly limited to presentation, can be cached by the client and all data is transferred through JSON API endpoints.
I would say that the best way to get data from Mongo into your page, is as mnemosyn said, using an API.
Basicly, you can have your API route, f.ex '/api/data' configured and then it can be used by a angular service, (which can use ngResource to make things easier). Any controller that wishes to access this data can use the angular service to get it, do some stuff with it, and then update it using the same angular service.

How can I use sails.js model with associations?

I want to create a node.js application using sails.js with the following DB design:
Products <----> ProductAttributes <----> Attributes
Please note that this is a given design and cannot be changed.
Althought sails.js does not support model associations yet, I want to know if it's possible for me to override the Model's CRUD methods or even create my own, in order to apply the above design to sails.js.
How can I do that?
If you want to get involved in the development of associations, send a note to the Google Group. In the mean time, what we do is, for SQL-based databases, use Model.query(), and for nosql databases, use two separate calls when you need to access the data.
Hope that helps, and look out for updates from us on this as the summer progresses.
You can use the associations in the Sails.js v0.10. npm install sails#git://github.com/balderdashy/sails.git#v0.10
and here is the documentation.. https://github.com/balderdashy/sails-docs/blob/master/reference/ModelAssociations.md

Angular services decoupling

I'm playing with angularjs doing some simple stuff. I wanted to incorporate some real time messaging like PubNub, PubSub or Pusher.
Basically I have it working, but it seems too cumbersome in some areas. Maybe you can show me a better way.
Ok, so here is my working jsfiddle (with pubsub faked) http://jsfiddle.net/canree/dD5VR/
I have external service (pubsub) and created angular service for it.
Now as I don't want other parts of my app to be dependent on this concrete implementation , I decided to create another one (inbox) that would store all the messages pubsub sent. And this inbox would be the dependency across my app (instead of pubsub).
So I want my dependencies to be:
controller -> inbox -> pubsub
When pubsub receives a message it needs to add it to inbox so that controller can see it and react accordingly. The problem is I don't want this backward dependency (pubsub -> inbox). I'd like pubsub to notify observers that message was received.
What I have now is ugly callback registration (inbox registers callback in pubsub). I don't like it very much as it has a lot of boilerplate (regarding this handling etc).
I wonder if there is other way to connect those services? Events (but without being forced to use $rootScope everywhere)? If so, where to register such event handler? Can services receive events?
Take a look at the fiddle provided and advice me how to solve it better way.
I don't want other parts of my app to be dependent on this concrete implementation
The interaction with the server is already wrapped/abstracted in the pubsub service. If the interaction with the server needs to change, it is already isolated to that service. I don't think adding another layer of abstraction buys you enough to offset the extra code you need to write (as you've already seen).
Here are a few other observations about how you could simplify your code (some of this you probably already know, but it might be instructive for others):
The content() function is not necessary (especially since messages is not private data). In Angular the controller $scope/model is often directly tied to a service model, so you could simply use:
$scope.messages = inbox.messages;
(If you like the content() function, consider making messages private in the inbox service.)
There is no need to send an event to the inbox controller about the change to inbox's messages array. The append() function just needs to call $rootScope.$digest(). And actually, this is probably not needed, since the real service would likely be using $http or $resource, which will automatically call $apply() or $digest. So _broadcastNewMessage() is not needed, nor is the $scope.$on() in the controller.
Even if you leave the content() function as is, you still won't need to broadcast anything.
Since inbox is dependent on pubsub, I would have the inbox service register itself
pubsub.subscribe(this.append, this);
pubsub's init() method can be in-line (no function required)
Fiddle with all of the above observations incorporated.
I wonder if there is other way to connect those services?
I can only think of model sharing (e.g., in service1: this.service1_obj_or_obj_property = service2.service2_obj_or_obj_property) and creating functions on the dependent service that the other service can call.
Can services receive events?
Since $on and $broadcast are defined on Scope, and since services are singletons and are not affected by scopes, I'm pretty sure the answer is "no."

RabbitMQ + Web Stomp and security

RabbitMQ + Web Stomp is awesome. However, I have some topics I would like secure as read-only or write-only.
It seems the only mechanism to secure these are with rabbitmqctl. I can create a vhost, a user and then apply some permissions. However, this is where then Stomp and Rabbit implementation starts to break down.
topics take form: /topic/blah in stomp, which routes to "amq.topic" in Rabbit with a routing key "blah". It would seem there is no way to set permissions for the routing key. Seems:
rabbitmqctl set_permissions -p vhost user ".*" ".*" "^amq\.topic"
is the best I can do, which is still "ALL" topics. I've looked into exchanges as well, but there is no way in javascript to define these on the fly.
Am I missing something here?
Reference: http://www.rabbitmq.com/blog/2012/05/14/introducing-rabbitmq-web-stomp/
Try this https://github.com/simonmacmullen/rabbitmq-auth-backend-http
It's much more flexible.
Basically it's small auth plugin for rabbit that delegates ACL decisions to a script over http (of which you have total control) which only has to reply with "allow" or "deny"
Yes, with RabbitMQ-WebStomp you're pretty much limited to normal RabbitMQ permissions set. It's not ideal, but you should be able to get basic permission setup right. Take a look at RabbitMQ docs:
http://www.rabbitmq.com/access-control.html
Quickly looking at the stomp docs:
http://www.rabbitmq.com/stomp.html
yes, you can't set up permissions for a particular routing key. Maybe you should use the 'exchange' semantics, plus bind an exchange with a queue explicitly (ie: don't use topics):
/exchange/exchange_name[/routing_key].
Please, do ask concrete questions about RMQ permissions on rabbitmq-discuss mailing list. People there are really helpful.
Unfortunately, RMQ permission set is not enough for some more complex scenarios. In this case you may want to:
Use STOMP only to read data, and publish messages only using some external AJAX interface that can speak directly to rabbit internally.
or, don't use web-stomp plugin and write a simple bridge between SockJS and RabbitMQ manually. This gives you more flexibility but requires more work.

Categories