Is there an easy way to limit a user's access to a tab on a screen

I am tasked with limiting users from gaining access to modify a panel on a screen. I have looked and can’t find an example of how this can be done. What might be the best way to tackle this.?

Classic or Kinetic?

Classic

Is the goal to keep people from seeing what is on that tab or just prevent them from changing the information? If it’s the latter, you could just make a Preprocessing Directive for the Update method and check if the user is part of some group that you create that allows them to change things and throw an error if they try to update. Or if it’s just a few fields, there is field level security that can be done.

It’s a lot harder to prevent them from accessing the tab at all. That I don’t know a good way to do.

1 Like

You can do BPM like @MLamkin suggested or use Field security to set certain users to read only status on the fields in question.

If you want to hide the entire tab, a customization of the Classic form would be required.

Yep, what’s the problem? Then we can advise better.

1 Like

The requirement is to keep certain users from changing the Ship To information on a Customer.

You could just fire the troublemakers.

Would it be helpful for them to still see it?

Yes they should be able to see but not change it

You could create a new security group. Give access to users who can change it.

Create a BPM. pre-processing, have a condition which says:
image
make it “Does-not belong to” and “new” group you created and end it with raise exception widget.

Next time when they try to change anything, it will throw error.

1 Like

Do these users need to enter other customer data? If not then just lock down all of Customer Maintenance and make them use Customer Tracker.

Otherwise then @MLamkin’s suggestion of a BPM will work and probably want to lock down the Customer GetNewShipTo method as well.

1 Like

If you want to disable the whole tab, but still have them see the data:

Make a security group like CannotEditShipToTab and put the users in it.

Then customize the screen.

public class Script
{
	//Use wizard to add adapter Ice.Adapters.SecGroup

	private EpiDataView edvShipTo;

	public void InitializeCustomCode()
	{
		this.edvShipTo = ((EpiDataView)(this.oTrans.EpiDataViews["ShipTo"]));
		this.edvShipTo.EpiViewNotification += new EpiViewNotification(this.edvShipTo_EpiViewNotification);
	}

	public void DestroyCustomCode()
	{
		this.edvShipTo.EpiViewNotification -= new EpiViewNotification(this.edvShipTo_EpiViewNotification);
		this.edvShipTo = null;
	}

	private void edvShipTo_EpiViewNotification(EpiDataView view, EpiNotifyArgs args)
	{
		if ((args.NotifyType == EpiTransaction.NotifyType.Initialize)) //Initialize
		{
			if ((args.Row > -1))
			{
				//Console.Beep(750, 125);
				if(CheckUserSecurityGroup("CannotEditShipToTab") == true) //Check if user is in Security Group
				{
					DisableControlsInDock("b14b0e70-4eed-4122-90c1-70b7ba3a5bb6"); //Guid of ShipToTab
				}
			}
		}
	}

	private void DisableControlsInDock(string dockGuidAsString)
	{
		var dock = csm.GetNativeControlReference(dockGuidAsString);

		foreach(Control childDock in dock.Controls)
		{
			if(childDock.Controls.Count > 0)
			{
				foreach(Control control in childDock.Controls)
				{
					control.Enabled = false;
				}
			}
		}
	}

	private bool CheckUserSecurityGroup(string securityGroupName, string otherUser = null)
	{
		bool returnValue = false;

		string currentUser = otherUser;

		if(String.IsNullOrEmpty(currentUser))
		{
		    EpiDataView edv = (EpiDataView)oTrans.EpiDataViews["CallContextClientData"];
		    currentUser     = edv.dataView[0]["CurrentUserId"].ToString();
		}

	    try
	    {
	        UserFileAdapter userFileAdapter = new UserFileAdapter(oTrans);
	        userFileAdapter.BOConnect();

	        bool result = userFileAdapter.GetByID(currentUser); 
	
	        if (result == true)
	        {
	            if ( userFileAdapter.UserFileData.UserFile[0]["GroupList"].ToString().ToLower().Contains(securityGroupName.ToLower()) )
	            {
	                returnValue = true;
	            }
	        }

	        userFileAdapter.Dispose();
	    }
	    catch (System.Exception ex)
	    {
	        ExceptionBox.Show(ex);
	    }
		
		return returnValue;
	}
}

1 Like

Thank You very much for all your help. I will try the suggestions I have received and try to see which one I can safely do. I am taking baby steps and hope to be running soon.

If I may send some feedback regarding code here.

  1. Whole logic checking if user has a security group could be moved to the function instead of being inside UI code. This will be needed anyway once they want switch to new Kinetic UI.
  2. Also this logic may be invoked only once to prevent checking the same thing every time in EpiViewNotification. Here I’m not sure 100% but it may actually be correct to check it every time if epicor for some reason enabling those controls back in some scenarios.

You may. :wink: Conversation always appreciated.

I prefer doing everything on the server, but without setting up and using the rest helper, or jose & josh’s library, or my function runner, that’s a lot of extra work, especially when there is an easy to use adapter available.

In this particular scenario, this code only runs once when the customer record is changed, verified by the console beep you see in the comments. It is necessary for this location to do that every time this dataview in intialized, as Epicor will re-enable the controls per header record selected.

As a side note, IMHO, … ahem… I wouldn’t do this at all, as this is a people problem, and should be addressed accordingly. I do however live in the real world and sometimes you do what you gotta do.


All that being said, I could set a script level boolean and check the security only once, but that’s not gonna save a lot of overhead, so I kept the example simple.

Thanks for the feedback. :tada:

2 Likes

That’s something I was worrying about.

One of my colleagues once told me that every system is working perfectly until you let people use it. :laughing:

When we have wanted to make some fields readonly and keep them that way, we put in some code on the backcolorchanged event for each of the fields and turn it back to readonly if it is no longer readonly. Kind of clunky, but it works.