sails.js: Lifecycle callbacks for Models: Do they support beforeFind and afterFind? - sails.js

In sails.js, Models support lifecycle callbacks for validate, create, update and destroy.
Is there support for callbacks for find() or query as well? Like beforeFind() and afterFind()?
The idea is same. I would want to validate / modify parameters before the query is run or after the query is run.
Any thoughts?

As of writing this it does NOT support these requests, however their is a pull request https://github.com/balderdashy/waterline/pull/525
You can use policies to do this in the mean time.

i don't get why this was left out in the first place. It's actually logical to want to add some data to the fetched model data after each model find.
The closest thing to afterFind in the documentation as of writting is customToJson model setting.
customToJSON: function() {
// Return a shallow copy of this record with the password and ssn removed.
return _.omit(this, ['password', 'ssn'])
}
you basically do your stuff before the return omit part. I still don't get why these lifecycles were omitted.
I think I am going to write a hook to provide these for now. I will post it here.

Related

REST new ID with DDD Aggregate

This question seemed fool at first sight for me, but then I realized that I don't have a proper answer yet, and interestingly also didn't find good explanation about it in my searches.
I'm new to Domain Driven Design concepts, so, even if the question is basic, feel free to add any considerations to it.
I'm designing in Rest API to configure Server Instances, and I came up with a Aggregate called Instance that contains a List of Configurations, only one specific Configuration will be active at a given time.
To add a Configuration, one would call an endpoint POST /instances/{id}/configurations with the body on the desired configuration. In response, if all okay, it would receive a HTTP 204 with a Header Location containing the new Configuration ID.
I'm planning to have only one Controller, InstanceController, that would call InstanceService that would manipulate the Instance Aggregate and then store to the Repo.
Since the ID's are generated by the repository, If I call Instance.addConfiguration and then InstanceRepository.store, how would I get the ID of the newly created configuration? I mean, it's a List, so It's not trivial as calling Instance.configuration.identity
A option would implement a method in Instance like, getLastAddedConfiguration, but this seems really brittle.
What is the general approach in this situation?
the ID's are generated by the repository
You could remove this extra complexity. Since Configuration is an entity of the Instance aggregate, its Id only needs to be unique inside the aggregate, not across the whole application. Therefore, the easiest is that the Aggregate assigns the ConfigurationId in the Instance.addConfiguration method (as the aggregate can easily ensure the uniqueness of the new Id). This method can return the new ConfigurationId (or the whole object with the Id if necessary).
What is the general approach in this situation?
I'm not sure about the general approach, but in my opinion, the sooner you create the Ids the better. For Aggregates, you'd create the Id before storing it (maybe a GUID), for entities, the Aggregate can create it the moment of creating/adding the entity. This allows you to perform other actions (eg publishing an event) using these Ids without having to store and retrieve the Ids from the DB, which will necessarily have an impact on how you implement and use your repositories and this is not ideal.

What are Reactors/Reactions in Event-Sourcing?

I am new in CQRS and I read about projections and projectors also reactors but my resource does not cover it thoroughly. Can someone define reactors thoroughly in Event sourcing or give me a link or book to read? my main questions are:
what are reactors?
what is the structure of reactors?
how do we implement reactors?
A projection is a function that receives a domain event and transforms it to an action on a list, tree, graph, whatever…
The idea here is that you want the semantic domain events to store them, and to be able to replay them, but that you need various interpretations of them to efficiently query them. Hence you need a projection that says that domain event X means INSERT or UPDATE or DELETE for a given view.
So, a projection is basically a mapping between domain events and CRUD operations. You might also say that a projection is one of many interpretations of a domain event.
Now, there may be actions requires in response to a domain event that are not related to updating a table. E.g., whenever you receive a userLoggedIn event, you may want to send an email to the user. It's like a simple if this then that rule. This is basically what you call a reaction. You just react to the domain event in some custom way.
The structure of a reactor (the component that reacts) is hence pretty similar to the one of a projector. The only difference is that a reactor does not update the read model, but does any arbitrary action you want to.
In other words: A projection is a special kind of a reaction, where it is always about updating the read model. Since this is so common, you have a dedicated pattern for this, but generally speaking: Whenever you do something in response to receiving an event, this is a reaction.
The question of how to implement reactors is hard to answer without having more details. In wolkenkit, a CQRS and event-sourcing framework for JavaScript and Node.js, reactors are nothing but flows. Flows can either be stateless flows or stateful flows, depending on whether they contain state themselves.
A simple example (which is of course specific to wolkenkit) may look like this:
'use strict';
const when = {
'userManagement.user.loggedIn' (event, mark) {
// ...
mark.asDone();
}
};
module.exports = { when };
(Disclaimer: I am one of the authors of wolkenkit, so please take the examples with a grain of salt.)

How to update data with GraphQL

I am studying graphql.
I can retrieve data from my mongo database with queries, I can create data with mutations.
But how I can modify existing data?
I am a bit lost here...
I have to create a new mutation?
Yes, every mutation describes a specific action that can be done to a bit of data. GraphQL is not like REST - it doesn't specify any standard CRUD-type actions.
When you are writing a mutation to update some data, you have two options. Let's explain them in the context of a todo item that has a completed status, and a text field:
Write mutations that represent semantic actions - markTodoCompleted, updateTodoText, etc.
Write a generic mutation that just sets any properties passed it, you could call it updateTodo.
I prefer the first approach, because it makes it more clear what the client is doing when it calls a certain mutation. In the second approach, you need to be careful to validate the values to be set to make sure someone can't set some invalid combination.
In short, you need to define your own mutations to update data.

Enrich Mongo documents in Meteor server-side when inserted from client-side?

I can't find anything in the docs, but in case I'm missing something, is there any way in Meteor to enrich documents inserted from the client on the server before they're sent to Mongo.
The use-case for this is to handle things like setting up timestamps and other (for server-side use only) fields, without having to set them as part of the document on the client.
The obvious method would be to use Meteor.call('addMyNewRecord', publicFields) then insert solely from the server-side, but I quite like having the minimongo api on the client-side and I'm hoping to avoid the call requirement. I know in CouchDB you can do some basic modifications in their on-update handler but can't seem to find anything similar for Meteor/Mongo.
I finally found a nice approach to doing this whilst still using the minimongo interface on the client-side.
It seems you can intercept the insert and enrich the documents as part of the Deny policy, like this:
myCollection.deny({
insert: function(userId, doc) {
doc.created = new Date().valueOf();
doc.creator = userId;
//other default fields
return false;
}
});
I've tried to do similar with the update Deny policy to add a modified field but that doesn't seem to work the same way. As noted in the post linked above, this won't work for the Allow policy.

How to inspect every query going to DB from Zend Framework

I have a complex reporting application that allows clients to login and view reports for their client data. There are several sections of the application where there are database calls, using various controllers. I need to make sure that client A doesn't get client B's information via header manipulation.
The system authenticates, and assignes them a clientID and roleID. If your roleID >1, that means you work for the company hosting the data, and you can see all client info. I want to create a catch-all that basically works like this:
if($roleID > 1) {
...send query to database
}else {
if(...does this query select a record with clientID other than my $auth->clientID){
do not execute query
}else {
execute query
}
}
The problem is, I want this to run for every query that goes to the server... how can I place this code as a "roadblock" between the application and the DB? I already use Zend_Profiler to look at queries, so I know it is somehow possible, but cannot discern this from the Profiler code...
I can always write an authentication function and pass selected queries that way, but this catch-all would be easier to implement across all of the calls and would be future proof. Any help is appreciated.
it's application design fault.
you shoud use 'service architecture' - the only one entry point for queries would be a service. and any checks inside it.
If this is something you want run on every query, I'd suggest extending Zend_Db_Select and overwrite either the query() or assemble() functions to add in your logic. You'll also want to add a way for it to be aware of your $auth object.
Another option is to extend your database adapter so you can intercept the queries directly. IMO, you should try and do this at the application level though.
Depending on your database server, you can put a trace on the DB side.
Here's an example for Oracle:
http://orafaq.com/wiki/SQL_Trace