Dexterity: Why won’t my Security operations show in Test Mode?


David Meego - Click for blog homepageI was recently assisting a fellow Dexterity developer to create scripts to automatically create all the Security Tasks and Security Roles for their ISV (Independent Software Vendor) add-on product for Microsoft Dynamics GP.

While they were checking their code in Dexterity Test mode, the security settings for their product never showed up. This was weird as the data appeared to be in the tables and worked when in Runtime mode.

What made this even more confusing, was that their code was very similar to my standard code and I could not find anything wrong with it. In my products, when I am in Test mode, the security settings show up correctly for me. I could not work out what was wrong.

After trying to troubleshoot the issue for a while, the other developer said they felt that the core Dynamics security window had a bug.

Bingo…. a light bulb lit up. From the dark recesses of my mind, I remembered that when Microsoft Dynamics GP version 10.0 first came out with its new pessimistic role and task based security model, I had a similar issue and so I had written triggers to fix it.

I opened one of my dictionaries and I found the triggers I had written. Reviewing the source code, I was able to rediscover what the bug was.

So, this article is to hopefully avoid further wasted time, by providing the triggers for you to add your dictionaries.


From the user interface, the issue is that your added dictionary resources (forms, tables and reports) do not show up in the Security Task Setup window.

security-task-entry

Remember that in Test mode, your dictionary resources will be in the Dynamics dictionary (ID = 0) rather than in your own add-on dictionary. But they don’t show up, even if you use Runtime_GetCurrentProductID() when adding your Security Operations to the Security Tasks.

The Listview on the Security Task Entry window is populated by a number form level procedures on the sySecurityTaskEntry form. Looking at the LoadFormsIntoLV, LoadFilesIntoLV and LoadReportsIntoLV form procedures, they all have similar code including the line that is causing our issue.

 if (DictID <> DYNAMICS and iResID >= 22000) or (DictID = DYNAMICS and iResID < 22000) then

The highlighted section is our problem; the if statement in the code specifically excludes 3rd party developer added resources (Resource ID >= 22000) in the Dynamics product from being displayed.

The other issue I found was that the 3rd Party series was not an option when the product is Dynamics. I usually place my resources into 3rd Party or System series depending on whether they are company or system based.

[Note: Before you tell me that 3rd party tables don’t work properly with SQL databases, I add the records into the SY_Pathnames table to make sure that the paths are defined for 3rd party series for both Dynamics and my product ID.]

The following excerpt from the Startup script and accompanying triggers will make your resources show in the window and add the 3rd party series to the drop-down list.

Security (excerpt)

if Runtime_GetCurrentProductID() = DYNAMICS then
	if Trigger_RegisterFocus(anonymous('(L) SecurityType' of window syTaskEntry of form sySecurityTaskEntry), TRIGGER_FOCUS_CHANGE, TRIGGER_AFTER_ORIGINAL, script WDC_sySecurityTaskEntry_SecurityType_POST) <> SY_NOERR then
		warning "SecurityType of window syTaskEntry of form sySecurityTaskEntry focus trigger registration failed.";
	end if;
	if Trigger_RegisterProcedure(script 'LoadFormsIntoLV' of form sySecurityTaskEntry, TRIGGER_AFTER_ORIGINAL, script WDC_sySecurityTaskEntry_LoadFormsIntoLV_POST) <> SY_NOERR then
		warning "LoadFormsIntoLV of form sySecurityTaskEntry procedure trigger registration failed.";
	end if;
	if Trigger_RegisterProcedure(script 'LoadReportsIntoLV' of form sySecurityTaskEntry, TRIGGER_AFTER_ORIGINAL, script WDC_sySecurityTaskEntry_LoadReportsIntoLV_POST) <> SY_NOERR then
		warning "LoadReportsIntoLV of form sySecurityTaskEntry procedure trigger registration failed.";
	end if;
	if Trigger_RegisterProcedure(script 'LoadFilesIntoLV' of form sySecurityTaskEntry, TRIGGER_AFTER_ORIGINAL, script WDC_sySecurityTaskEntry_LoadFilesIntoLV_POST) <> SY_NOERR then
		warning "LoadFilesIntoLV of form sySecurityTaskEntry procedure trigger registration failed.";
	end if;
end if;

WDC_sySecurityTaskEntry_SecurityType_POST

if Runtime_GetCurrentProductID() <> DYNAMICS then
	abort script;
end if;

if isopen(window syTaskEntry of form sySecurityTaskEntry) then
	if  DictID of window syTaskEntry of form sySecurityTaskEntry = DYNAMICS then
		case itemdata('(L) SecurityType' of window syTaskEntry of form sySecurityTaskEntry,'(L) SecurityType' of window syTaskEntry of form sySecurityTaskEntry)
			in [TYPE_WINDOWS of form sySecurityTaskEntry, TYPE_REPORTS of form sySecurityTaskEntry, TYPE_FILES of form sySecurityTaskEntry]
				add item getmsg(14045), SERIES_3RDPARTY of form sySecurityTaskEntry to '(L) SecuritySeries' of window syTaskEntry of form sySecurityTaskEntry;
			else
		end case;
	end if;
end if;

WDC_sySecurityTaskEntry_LoadFormsIntoLV_POST

in	long	IN_Series;

local integer count,i,iResID,iResType, iSeries;
local string item1;

local sySecurityTaskOperationsState		TaskOperationsState;
local long nStatus;

default form to sySecurityTaskEntry;
default window to syTaskEntry;

if Runtime_GetCurrentProductID() <> DYNAMICS then
	abort script;
end if;

nStatus = Create(TaskOperationsState, table sySecurityAssignTaskOperations) of form sySecurityTaskOperations;
if nStatus <> OKAY then
	abort script;
end if;

set iResType to SERIES_FORMS;
iSeries = integer(IN_Series);

count = Resource_StartSeriesFill(DictID, iResType, iSeries);
for i equals 1 to count do
	iResID = Resource_GetInfo(DictID, iResType, i, item1);
	if (DictID = DYNAMICS and iResID >= 22000) then
		if iResID <> 0 and (item1 <> SECURITY_WINDOWFILTER and item1 <> SECURITY_SBMFILTER) and not WDC_Exclude_From_Security(DictID, iResID, Restype) then 
			call SetIndex of form sySecurityTaskOperations, TaskOperationsState, 'Security Task ID', DictID, iResID, Restype;
			nStatus = Get(TaskOperationsState, GET + EQUAL) of form sySecurityTaskOperations;
			if nStatus = OKAY then {has access}
				call LoadListView of form sySecurityTaskEntry, item1, iResID, Restype, DictID, true;
			else
				call LoadListView of form sySecurityTaskEntry, item1, iResID, Restype, DictID, false;
			end if;
		end if;
	end if;
end for;
Resource_EndSeriesFill();

call ClearRange of form sySecurityTaskOperations, TaskOperationsState;
call Destroy of form sySecurityTaskOperations, TaskOperationsState;

WDC_sySecurityTaskEntry_LoadReportsIntoLV_POST

in	long	IN_Series;

local integer count,i,iResID,iResType, iSeries;
local string item1;

local sySecurityTaskOperationsState		TaskOperationsState;
local long nStatus;

default form to sySecurityTaskEntry;
default window to syTaskEntry;

if Runtime_GetCurrentProductID() <> DYNAMICS then
	abort script;
end if;

nStatus = Create(TaskOperationsState, table sySecurityAssignTaskOperations) of form sySecurityTaskOperations;
if nStatus <> OKAY then
	abort script;
end if;

set iResType to SERIES_REPORTS;
iSeries = integer(IN_Series);

count = Resource_StartSeriesFill(DictID, iResType, iSeries);
for i equals 1 to count do
	iResID = Resource_GetInfo(DictID, iResType, i, item1);
	if (DictID = DYNAMICS and iResID >= 22000) then
		if iResID <> 0 and (item1 <> SECURITY_WINDOWFILTER and item1 <> SECURITY_SBMFILTER) and not WDC_Exclude_From_Security(DictID, iResID, Restype) then 
			call SetIndex of form sySecurityTaskOperations, TaskOperationsState, 'Security Task ID', DictID, iResID, Restype;
			nStatus = Get(TaskOperationsState, GET + EQUAL) of form sySecurityTaskOperations;
			if nStatus = OKAY then {has access}
				call LoadListView of form sySecurityTaskEntry, item1, iResID, Restype, DictID, true;
			else
				call LoadListView of form sySecurityTaskEntry, item1, iResID, Restype, DictID, false;
			end if;
		end if;
	end if;
end for;
Resource_EndSeriesFill();

call ClearRange of form sySecurityTaskOperations, TaskOperationsState;
call Destroy of form sySecurityTaskOperations, TaskOperationsState;

WDC_sySecurityTaskEntry_LoadFilesIntoLV_POST

in	long	IN_Series;

local integer count,i,iResID,iResType, iSeries;
local string item1;
local sySecurityTaskOperationsState		TaskOperationsState;
local long nStatus;

default form to sySecurityTaskEntry;
default window to syTaskEntry;

if Runtime_GetCurrentProductID() <> DYNAMICS then
	abort script;
end if;

nStatus = Create(TaskOperationsState, table sySecurityAssignTaskOperations) of form sySecurityTaskOperations;
if nStatus <> OKAY then
	abort script;
end if;

set iResType to SERIES_PFILES;
iSeries = integer(IN_Series);

count = Resource_StartSeriesFill(DictID, iResType, iSeries);
for i equals 1 to count do
	iResID = Resource_GetInfo(DictID, iResType, i, item1);
	if (DictID = DYNAMICS and iResID >= 22000) then
		if iResID <> 0 and (item1 <> SECURITY_WINDOWFILTER and item1 <> SECURITY_SBMFILTER) and not WDC_Exclude_From_Security(DictID, iResID, Restype) then 
			call SetIndex of form sySecurityTaskOperations, TaskOperationsState, 'Security Task ID', DictID, iResID, Restype;
			nStatus = Get(TaskOperationsState, GET + EQUAL) of form sySecurityTaskOperations;
			if nStatus = OKAY then {has access}
				call LoadListView of form sySecurityTaskEntry, item1, iResID, Restype, DictID, true;
			else
				call LoadListView of form sySecurityTaskEntry, item1, iResID, Restype, DictID, false;
			end if;

		end if;
	end if;
end for;
Resource_EndSeriesFill();

call ClearRange of form sySecurityTaskOperations, TaskOperationsState;
call Destroy of form sySecurityTaskOperations, TaskOperationsState;

Just add this code and you will be able to see your security settings while in test mode as long as you are using Runtime_GetCurrentProductID() to specify your product dictionary.

Hope this is useful

David

This article was originally posted on http://www.winthropdc.com/blog.

Advertisements

3 thoughts on “Dexterity: Why won’t my Security operations show in Test Mode?

Please post feedback or comments

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s