Customizing TApplication Without Helpers

Have you ever wished you could create a TApplication descendant to incorporate some core functionality you wanted across all your applications?  We did, and this post describes how we accomplished it in Delphi 7 which does not support class helpers.

One of the fundamental features Delphi lacks for “out of the box” enterprise application development is the ability to determine whether the current logged in user belongs to an Active Directory group directly, or indirectly through memberships in other groups.  This is essential for determining if the user is allowed to run the application at all, and if so, what subset of the application’s features they are allowed to access.

At work, we maintain a DEV, TEST and PROD database environment.  Our applications accept this environment specifier as a command line parameter.  We dynamically change our database connections at run-time, and restrict access to the applications on the file system using AD groups.  Some of our applications used Oracle database tables in the application’s schema for security, and to record their usage.  Since there was no consistent schema used for all applications, this was difficult to maintain and any applications with security were usually accompanied by a “Security Manager” companion application.  The development group wanted to off load all the user provisioning support calls we received, to the service desk, so we had to provide a uniform security mechanism they could administrate - AD.

The Requirements

My experience has taught me that full blown requirements gathering just doesn’t work, nor does diving into code.  I prefer a middle of the road approach.  I like to create a point form list of application requirements, and then prototype it to see how well it works, driving out more ideas.

My requirements for this effort were:

  • prevent users from running the application if they did not belong to the appropriate group(s)
  • provide easy access to AD Membership information for securing application features
  • must be easily incorporated into existing applications with minimal changes (including apps not requiring security)
  • incorporate our standard About box
  • provide some basic roles and allow developer defined ones
  • provide application version information

The Implementation

Initially I started by developing components that could provide AD Group membership information.  Then we standardized on a group naming convention, taking into account the multiple database environments we needed to support:

Format(’%s - %s - %s’,[ApplicationName,Environment,RoleName]);  //i.e.: ‘HierarchyMgr - DEV - PowerUsers’

TApplication was never really meant to be used as an ancestor class.  None of it’s methods are virtual, it’s presence in the Forms unit and tight coupling to TForm and other classes speak to this.  So I traced through the sequence of code excecuted on application startup and found that the only way I could load my own application object instead of TApplication was to make my unit the first one in the uses clause of a project.  Then in my initialization I can free the existing application object, replacing it with my own using the following code:

initialization
if assigned(Forms.Application) then
Forms.Application.Free;

Application := TEnApplication.Create(nil);
Application.ShowHint := True;
//in case any units access the Forms.Application global variable explicitly, assign it to the same instance
Forms.Application := Application;

finalization
//Application object will be destroyed by native Delphi VCL

If you’re interested in the actual code, send me an email…

Tags: ,

Leave a Reply