In a Windows forms payroll application employing MVP
pattern (for a small scale client) I'm planing user permission handling as follows (permission based) as basically its implementation should be less complicated and straightforward.
NOTE: System could be simultaneously used by few users (maximum 3) and the database is at the server side.
This is my UserModel
. Each user has a list of permissions given for them.
class User
{
string UserID { get; set; }
string Name { get; set; }
string NIC {get;set;}
string Designation { get; set; }
string PassWord { get; set; }
List <string> PermissionList = new List<string>();
bool status { get; set; }
DateTime EnteredDate { get; set; }
}
When user login to the system it will keep the current user in memory.
For example in BankAccountDetailEntering
view, I can control the permission to access a command button as follows.
public partial class BankAccountDetailEntering : Form
{
bool AccountEditable {get; set;}
public BankAccountDetailEntering ()
{
InitializeComponent();
}
private void BankAccountDetailEntering_Load(object sender, EventArgs e)
{
cmdEditAccount.enabled = false;
OnLoadForm (sender, e); // Event fires...
If (AccountEditable )
{
cmdEditAccount.enabled=true;
}
}
}
In this purpose all relevant presenters (like BankAccountDetailPresenter
) should aware of UserModel
as well in addition to the corresponding business Model
it is presenting to the View
.
class BankAccountDetailPresenter
{
BankAccountDetailEntering _View;
BankAccount _Model;
User _UserModel;
DataService _DataService;
BankAccountDetailPresenter( BankAccountDetailEntering view, BankAccount model, User userModel, DataService dataService )
{
_View=view;
_Model = model;
_UserModel = userModel;
_DataService = dataService;
WireUpEvents();
}
private void WireUpEvents()
{
_View.OnLoadForm += new EventHandler(_View_OnLoadForm);
}
private void _View_OnLoadForm(Object sender, EventArgs e)
{
foreach(string s in _UserModel.PermissionList)
{
If( s =="CanEditAccount")
{
_View.AccountEditable =true;
return;
}
}
}
public Show()
{
_View.ShowDialog();
}
}
So I'm handling the user permissions in the presenter iterating through the list. Should this be performed in the Presenter
or View
? Any other more promising ways to do this? I'd appreciate it if you could review the code and provide your feedback.
1 Answer 1
Full disclosure: I haven't done much with windows forms applications, so I may be breaking some otherwise well known winforms programming patterns.
Permissions are better handled by a service, so that you can more easily unit test that layer, plus the permissions logic becomes portable between presenters to promote DRYness of your code (Don't Repeat Yourself).
public class UserPermissionsService
{
private User _user = null;
public UserPermissionsService(User user)
{
_user = user;
}
public bool CanEditAccount { get { return _user.PermissionList.Contains("CanEditAccount"); } }
}
Then to use it:
public partial class BankAccountDetailEntering : Form
{
UserPermissionsService PermissionsService { get; set; }
public BankAccountDetailEntering()
{
InitializeComponent();
}
private void BankAccountDetailEntering_Load(object sender, EventArgs e)
{
cmdEditAccount.enabled = PermissionsService.CanEditAccount;
}
}
The BankAccountDetailEntering
form would need to instantiate the user permissions service with the proper user object before the BankAccountDetailEntering_Load
method gets called.
-
\$\begingroup\$ Thanks for the answer. I cant understand the use of property UserPermissionsService PermissionsService { get; set; } in the form!. When instantiating
user
, the problem is how to keep the logeduser
object in memory and make it available for thisBankAccountDetailEntering
form? \$\endgroup\$CAD– CAD2014年06月10日 11:35:59 +00:00Commented Jun 10, 2014 at 11:35 -
\$\begingroup\$ I also had the same question, about how to get the
user
object. Where do you instantiate theBankAccountDetailPresenter
object, because the user is passed into the constructor. \$\endgroup\$Greg Burghardt– Greg Burghardt2014年06月10日 12:51:11 +00:00Commented Jun 10, 2014 at 12:51 -
\$\begingroup\$ Method injection solved the matter;) Program.cs instantiates the service and then, when the user details became available, the presenter inject the user to service object. Then the presenter assigns service instance to the said property in the form. So that load event can manage things as you said. Thank you very much! \$\endgroup\$CAD– CAD2014年06月10日 13:31:54 +00:00Commented Jun 10, 2014 at 13:31