Suppose we have a before save logic hook on leads, now How we can detect if this called logic hook is:
a crm user who is saving a lead form
is a lead captured from on of entry points
is a save triggered by soap calls
is a workflow which is modifying lead fields
is called because of csv import
...
I have checked some of the behaviors, it seems logic hooks are not called on workflows (at least in my test)
Also I hope to figure out this issue in global variables, but there are a lot of global variables.
So How I can detect caller of a logic hook ?
The best way that I found to figure this out is to add a:
$GLOBALS['log']->fatal(print_r($_REQUEST,true));
To your logic hook. Then test each scenario that you need to account for and see how the request differs. Also check $_SESSION. You'll be able to find a few things that you can depend upon for your logic.
That's what I did eventually. I share some of my observations so it may help the others (these are statements, based on the case some of them may applies)
in third party entry point calls $_SESSION is empty, in direct entry point calls is not so. Also in rest calls session is not empty.
rest calls have $_REQUEST[rest_data] and others don't.
entry point calls have $_REQUEST[entryPoint] available in the array
global $current_user is available, but the id var ($current_user->id) is a string only in the case a user is submitting a form in crm.
in inline editing $_REQUEST[action] is equal to saveHTMLField
in user calls $_SERVER[HTTP_USER_AGENT] is available and in other calls it is not.
In a simple case this code shows how to detect user calls:
$trigger = false;
global $current_user;
if (!isset($current_user->id) || !strlen($current_user->id) > 2)
$trigger = true;
if ($trigger) {
//#My Custome Code
}
Related
Can anyone tell me offhand if SVN::Hooks::Notify's NOTIFY and NOTIFY_DEFAULTS blocks replace (or rather, stop the evaluation of) the POST_COMMIT block? My PRE_COMMIT block works fine, and my existing NOTIFY/NOTIFY_DEFAULTS blocks process just fine.
However, nothing I have under the POST_COMMIT block fires at all... and yes, hooks/post-commit is linked to the script. The perdocs for svn::hooks::notify state that it runs within POST_COMMIT, but I would prefer to do some extra processing first before kicking off a notification email (eg, inserting pertinent information into a db table for later use).
The NOTIFY block sets a post-commit hook; there is no separate hook for notify.
And as far as I can tell from the SVN::Hook source, you can have set as many of a given hook as you want, and they will run in the order you add them in. So you may need to do e.g.:
use SVN::Hooks;
BEGIN {
POST_COMMIT { ... }
}
use SVN::Hooks::Notify;
to have your other hook come before the notify hook.
I made a question that looked like this before and people didn't understand. I'll try to be more concise and will use a comparison with Ajax used in web applications.
I have the main form. There I have one button that will extract data from a field and send to a second form, a window that will pop up and display the data in a more organized way (A TListBox).
I would like to know if there is a way to on SecondForm.Show to send this data as parameters, like SecondForm.Show(data).
The comparison to Ajax is that when you make an Ajax Call from a html page to the server, you send encapsulated data, the server receives it and works with it.
I want my main form to send the data, the second form to receive the data and use it.
Is it possible? How?
If I were you, I'd add parameters to the form's constructor so that it has all the information it needs from the moment it exists.
constructor TSecondFrom.Create(AOwner: TComponent; AParam1: Integer; const AParam2: string);
begin
inherited Create(AOwner);
// Use or store parameters here
end;
You're welcome to write some other method instead, though, and you can call it Show, if you want. Define it to accept whatever parameters you need, and when you're ready, you can call the inherited zero-argument Show method to make the form appear.
procedure TSecondForm.Show(AParam1: Integer; const AParam2: string);
begin
// Use parameters here.
inherited Show;
end;
Decide in what form to send the data from Main to SecondFrom. For instance in a TStringList. Fill the striglist on the mainform, use it as parameter in SecondForm.Show.
This is the answer from your other question that you deleted. It still applies I believe.
Always prefer passing state in the constructor if that is viable.
Problems with state occur when it changes. Multi-threading is confounded by mutating state. Code that makes copies of state become out of sync if the state changes later.
Objects cannot be used while the constructor is executing. That's the time to mutate state since no other party can see the effects of that mutation. Once the constructor returns the newly minted object to its new owner, it is fully initialized.
It's hard with an OOP style to limit all mutation to constructors. Few, if any, libraries admit that style of coding. However, the more mutation you push into the constructor, the lower the risk of being caught out later.
In reality, for your scenario, I suspect that these risks are minimal. However, as a general principle, initialization during construction is sound and it makes sense to adhere to the principle uniformly.
I'm evaluating backbone.js as a potential javascript library for use in an application which will have a few different backends: WebSocket, REST, and 3rd party library producing JSON. I've read some opinions that backbone.js works beautifully with RESTful backends so long as the api is 'by the book' and follows the appropriate http verbage. Can someone elaborate on what this means?
Also, how much trouble is it to get backbone.js to connect to WebSockets? Lastly, are there any issues with integrating a backbone.js model with a function which returns JSON - in other words does the data model always need to be served via REST?
Backbone's power is that it has an incredibly flexible and modular structure. It means that any part of Backbone you can use, extend, take out, or modify. This includes the AJAX functionality.
Backbone doesn't "care" where do you get the data for your collections or models. It will help you out by providing an out of the box RESTful "ajax" solution, but it won't be mad if you want to use something else!
This allows you to find (or write) any plugin you want to handle the server interaction. Just look on backplug.io, Google, and Github.
Specifically for Sockets there is backbone.iobind.
Can't find a plugin, no worries. I can tell you exactly how to write one (it's 100x easier than it sounds).
The first thing that you need to understand is that overwriting behavior is SUPER easy. There are 2 main ways:
Globally:
Backbone.Collection.prototype.sync = function() {
//screw you Backbone!!! You're completely useless I am doing my own thing
}
Per instance
var MySpecialCollection = Backbone.Collection.extend({
sync: function() {
//I like what you're doing with the ajax thing... Clever clever ;)
// But for a few collections I wanna do it my way. That cool?
});
And the only other thing you need to know is what happens when you call "fetch" on a collection. This is the "by the book"/"out of the box behavior" behavior:
collection#fetch is triggered by user (YOU). fetch will delegate the ACTUAL fetching (ajax, sockets, local storage, or even a function that instantly returns json) to some other function (collection#sync). Whatever function is in collection.sync has to has to take 3 arguments:
action: create (for creating), action: read (for fetching), delete (for deleting), or update (for updating) = CRUD.
context (this variable) - if you don't know what this does it, don't worry about it, not important for now
options - where da magic is. We only care about 1 option though
success: a callback that gets called when the data is "ready". THIS is the callback that collection#fetch is interested in because that's when it takes over and does it's thing. The only requirements is that sync passes it the following 1st argument
response: the actual data it got back
Now
has to return a success callback in it's options that gets executed when it's done getting the data. That function what it's responsible for is
Whenever collection#sync is done doing it's thing, collection#fetch takes back over (with that callback in passed in to success) and does the following nifty steps:
Calls set or reset (for these purposes they're roughly the same).
When set finishes, it triggers a sync event on the collection broadcasting to the world "yo I'm ready!!"
So what happens in set. Well bunch of stuff (deduping, parsing, sorting, parsing, removing, creating models, propagating changesand general maintenance). Don't worry about it. It works ;) What you need to worry about is how you can hook in to different parts of this process. The only two you should worry about (if your wraps data in weird ways) are
collection#parse for parsing a collection. Should accept raw JSON (or whatever format) that comes from the server/ajax/websocket/function/worker/whoknowwhat and turn it into an ARRAY of objects. Takes in for 1st argument resp (the JSON) and should spit out a mutated response for return. Easy peasy.
model#parse. Same as collection but it takes in the raw objects (i.e. imagine you iterate over the output of collection#parse) and splits out an "unwrapped" object.
Get off your computer and go to the beach because you finished your work in 1/100th the time you thought it would take.
That's all you need to know in order to implement whatever server system you want in place of the vanilla "ajax requests".
I am new to Lift and I am thinking whether I should investigate it more closely and start using it as my main platform for the web development. However I have few "fears" which I would be happy to be dispelled first.
Security
Assume that I have the following snippet that generates a form. There are several fields and the user is allowed to edit just some of them.
def form(in : NodeSeq): NodeSeq = {
val data = Data.get(...)
<lift:children>
Element 1: { textIf(data.el1, data.el1(_), isEditable("el1")) }<br />
Element 2: { textIf(data.el2, data.el2(_), isEditable("el2")) }<br />
Element 3: { textIf(data.el3, data.el3(_), isEditable("el3")) }<br />
{ button("Save", () => data.save) }
</lift:children>
}
def textIf(label: String, handler: String => Any, editable: Boolean): NodeSeq =
if (editable) text(label, handler) else Text(label)
Am I right that there is no vulnerability that would allow a user to change a value of some field even though the isEditable method assigned to that field evaluates to false?
Performance
What is the best approach to form processing in Lift? I really like the way of defining anonymous functions as handlers for every field - however how does it scale? I guess that for every handler a function is added to the session with its closure and it stays there until the form is posted back. Doesn't it introduce some potential performance issue when it comes to a service under high loads (let's say 200 requests per second)? And when do these handlers get freed (if the form isn't resubmitted and the user either closes the browser or navigate to another page)?
Thank you!
With regards to security, you are correct. When an input is created, a handler function is generated and stored server-side using a GUID identifier. The function is session specific, and closed over by your code - so it is not accessible by other users and would be hard to replay. In the case of your example, since no input is ever displayed - no function is ever generated, and therefore it would not be possible to change the value if isEditable is false.
As for performance, on a single machine, Lift performs incredibly well. It does however require session-aware load balancing to scale horizontally, since the handler functions do not easily serialize across machines. One thing to remember is that Lift is incredibly flexible, and you can also create stateless form processing if you need to (albeit, it will not be as secure). I have never seen too much of a memory hit with the applications we have created and deployed. I don't have too many hard stats available, but in this thread, David Pollak mentioned that demo.liftweb.net at the time had 214 open sessions consuming about 100MB of ram (500K/session).
Also, here is a link to the Lift book's chapter on Scalability, which also has some more info on security.
The closure and all the stuff is surely cleaned at sessionShutdown. Earlier -- I don't know. Anyway, it's not really a theoretical question -- it highly depends on how users use web forms in practice. So, for a broader answer, I'd ask the question on the main channel of liftweb -- https://groups.google.com/forum/#!forum/liftweb
Also, you can use a "statical" form if you want to. But AFAIK there are no problems with memory and everybody is using the main approach to forms.
If you don't create the handler xml/html -- the user won't be able to change the data, that's for sure. In your code, if I understood it correctly (I'm not sure), you don't create "text(label,handler)" when it's not needed, so everything's secure.
I run into this regularly, and am just looking for best practice/approach. I have a database / datamodule-containing app, and want to fire up the database/datasets on startup w/o having "active at runtime" set to true at design time (database location varies). Also run a web "check for updates" routine when the app starts up.
Given TForm event sequences, and results from various trial and error, I'm currently using this approach:
I use a "Globals" record set up in the main form to store all global vars, have one element of that called Globals.AppInitialized (boolean), and set it to False in the Initialization section of the main form.
At the main form's OnShow event (all forms are created by then), I test Globals.AppInitialized; if it's false, I run my "Initialization" stuff, and then finish by setting Globals.AppInitialized := True.
This seems to work pretty well, but is it the best approach? Looking for insight from others' experience, ideas and opinions. TIA..
I generally always turn off auto creation of all forms EXCEPT for the main form and possibly the primary datamodule.
One trick that I learned you can do, is add your datamodule to your project, allow it to auto-create and create BEFORE your main form. Then, when your main form is created, the onCreate for the datamodule will have already been run.
If your application has some code to say, set the focus of a control (something you can't do on creation, since its "not visible yet") then create a user message and post it to the form in your oncreate. The message SHOULD (no guarantee) be processed as soon as the forms message loop is processed. For example:
const
wm_AppStarted = wm_User + 101;
type
Form1 = class(tForm)
:
procedure wmAppStarted(var Msg:tMessage); message wm_AppStarted;
end;
// in your oncreate event add the following, which should result in your wmAppStarted event firing.
PostMessage(handle,wm_AppStarted,0,0);
I can't think of a single time that this message was never processed, but the nature of the call is that it is added to the message queue, and if the queue is full then it is "dropped". Just be aware that edge case exists.
You may want to directly interfere with the project source (.dpr file) after the form creation calls and before the Application.Run. (Or even earlier in case.)
This is how I usually handle such initialization stuff:
...
Application.CreateForm(TMainForm, MainForm);
...
MainForm.ApplicationLoaded; // loads options, etc..
Application.Run;
...
I don't know if this is helpful, but some of my applications don't have any form auto created, i.e. they have no mainform in the IDE.
The first form created with the Application object as its owner will automatically become the mainform. Thus I only autocreate one datamodule as a loader and let this one decide which datamodules to create when and which forms to create in what order. This datamodule has a StartUp and ShutDown method, which are called as "brackets" around Application.Run in the dpr. The ShutDown method gives a little more control over the shutdown process.
This can be useful when you have designed different "mainforms" for different use cases of your application or you can use some configuration files to select different mainforms.
There actually isn't such a concept as a "global variable" in Delphi. All variables are scoped to the unit they are in and other units that use that unit.
Just make the AppInitialized and Initialization stuff as part of your data module. Basically have one class (or datamodule) to rule all your non-UI stuff (kind of like the One-Ring, except not all evil and such.)
Alternatively you can:
Call it from your splash screen.
Do it during log in
Run the "check for update" in a background thread - don't force them to update right now. Do it kind of like Firefox does.
I'm not sure I understand why you need the global variables? Nowadays I write ALL my Delphi apps without a single global variable. Even when I did use them, I never had more than a couple per application.
So maybe you need to first think why you actually need them.
I use a primary Data Module to check if the DB connection is OK and if it doesn't, show a custom component form to setup the db connection and then loads the main form:
Application.CreateForm(TDmMain, DmMain);
if DmMain.isDBConnected then
begin
Application.CreateForm(TDmVisualUtils, DmVisualUtils);
Application.CreateForm(TfrmMain, frmMain);
end;
Application.Run;
One trick I use is to place a TTimer on the main form, set the time to something like 300ms, and perform any initialization (db login, network file copies, etc). Starting the application brings up the main form immediately and allows any initialization 'stuff' to happen. Users don't startup multiple instances thinking "Oh..I didn't dbl-click...I'll do it again.."