patterncsharpMinor
Setting user permissions, where certain permissions imply other permissions
Viewed 0 times
implypermissionsuserwhereothersettingcertain
Problem
The purpose of the class is to set permissions for a user. These include delete, download, upload, view, etc. These properties often depend on other properties, and setting them has side effects.
For example, if I set
You can see this starts to get a bit convoluted. Especially when you through in account preferences that relax/tighten the relationships and force disable some of the permissions (which is important since I'm binding this to UI and want to enable/disable checkboxes).
The code works as-is, but it is very difficult to maintain and understand all of the relationships and side-effects. If someone is new to the code it can be a trip trying to figure out how properties depend on and change other properties (even more so when you get to doubly nested dependencies like
Can I make the relationships any clearer or easier to work with? I'm assuming it's more than just an issue of documentation, but maybe not.
One thought was to have one big method that all of the setters call at the end. That one method would enforce all of the relationships. Not sure if this can satisfy every condition or if it's a good idea though.
```
public class AccessControlViewModel : INotifyPropertyChanged
{
private AccountPreferences Preferences => CurrentUser.Account.Preferences;
private bool AllowDownloadNotificationsWithoutAdmin => Preferences.AllowDownloadNotificationsWithoutAdmin;
private bool ShowDownloadLinkInUploadNotification => Preferences.ShowDownloadLinkInUploadNotification;
public AccessControl AccessControl { get; privat
For example, if I set
CanUpload=false, then I need to also set CanManagePermissions=false since you cannot be an admin without upload permission. Likewise, if I set CanManagePermissions=true, then I need to set delete, download, and upload to true. Plus, you can't have CanDownload permission without also having CanView permission, so I set that too. But you can have CanView without CanDownload.You can see this starts to get a bit convoluted. Especially when you through in account preferences that relax/tighten the relationships and force disable some of the permissions (which is important since I'm binding this to UI and want to enable/disable checkboxes).
The code works as-is, but it is very difficult to maintain and understand all of the relationships and side-effects. If someone is new to the code it can be a trip trying to figure out how properties depend on and change other properties (even more so when you get to doubly nested dependencies like
CanManagePermissions->CanDownload->CanView).Can I make the relationships any clearer or easier to work with? I'm assuming it's more than just an issue of documentation, but maybe not.
One thought was to have one big method that all of the setters call at the end. That one method would enforce all of the relationships. Not sure if this can satisfy every condition or if it's a good idea though.
```
public class AccessControlViewModel : INotifyPropertyChanged
{
private AccountPreferences Preferences => CurrentUser.Account.Preferences;
private bool AllowDownloadNotificationsWithoutAdmin => Preferences.AllowDownloadNotificationsWithoutAdmin;
private bool ShowDownloadLinkInUploadNotification => Preferences.ShowDownloadLinkInUploadNotification;
public AccessControl AccessControl { get; privat
Solution
It appears that business logic (" I set
Your
After validation has passed, you really need a collection of classes that represents the "Problem Domain" - managing permissions, like say a
Here the relationship between uploading and managing permissions is enforced.
You really need a separate of UI logic from Business Logic.
CanUpload=false, then I need to also set CanManagePermissions=false since you cannot be an admin without upload permission") is being mixed up with the user interface presentation.Your
AccessControlViewModel should just be a strongly typed bag of data representing what the user has chosen on a form. After pressing a button, you should then validate the entries in the form.After validation has passed, you really need a collection of classes that represents the "Problem Domain" - managing permissions, like say a
User class:public class User
{
public bool CanUpload { get; private set; }
public bool CanManagePermissions { get; private set; }
public void CanAllowUploads
{
get { return CanManagePermissions; }
}
public void AllowUploads()
{
if (!CanAllowUploads)
throw new InvalidOperationException("Cannot allow uploads without being able to manage permissions");
CanUpload = true;
}
public void DisallowUploads()
{
CanUpload = false;
}
public void AllowPermissionManagement()
{
CanManagePermissions = true;
}
public void DisallowPermissionManagement()
{
CanUpload = false;
CanManagePermissions = false;
}
}Here the relationship between uploading and managing permissions is enforced.
User user = new User();
user.AllowUploads(); // Throws InvalidOperationException
user.AllowPermissionManagement();
user.AllowUploads(); // No exception gets thrown
user.CanUpload // Is True
user.CanManagePermissions // Is True
user.DisallowPermissionManagement();
user.CanUpload // Is False
user.CanManagePermissions // Is FalseYou really need a separate of UI logic from Business Logic.
Code Snippets
public class User
{
public bool CanUpload { get; private set; }
public bool CanManagePermissions { get; private set; }
public void CanAllowUploads
{
get { return CanManagePermissions; }
}
public void AllowUploads()
{
if (!CanAllowUploads)
throw new InvalidOperationException("Cannot allow uploads without being able to manage permissions");
CanUpload = true;
}
public void DisallowUploads()
{
CanUpload = false;
}
public void AllowPermissionManagement()
{
CanManagePermissions = true;
}
public void DisallowPermissionManagement()
{
CanUpload = false;
CanManagePermissions = false;
}
}User user = new User();
user.AllowUploads(); // Throws InvalidOperationException
user.AllowPermissionManagement();
user.AllowUploads(); // No exception gets thrown
user.CanUpload // Is True
user.CanManagePermissions // Is True
user.DisallowPermissionManagement();
user.CanUpload // Is False
user.CanManagePermissions // Is FalseContext
StackExchange Code Review Q#128173, answer score: 3
Revisions (0)
No revisions yet.