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 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; private set; }
public bool HasChanged { get; private set; }
public bool CanUpload
{
get
{
return AccessControl.CanUpload.GetValueOrDefault();
}
set
{
if (AccessControl.CanUpload != value)
{
AccessControl.CanUpload = value;
RaisePropertyChanged(nameof(CanUpload));
if (!value)
{
CanManagePermissions = false;
if (EnableViewOnly)
{
CanView = true;
}
else
{
CanDownload = true;
}
}
HasChanged = true;
RaisePropertyChanged(nameof(PermissionSummary));
}
}
}
public bool CanDownload
{
get
{
return AccessControl.CanDownload.GetValueOrDefault();
}
set
{
if (AccessControl.CanDownload != value)
{
AccessControl.CanDownload = value;
RaisePropertyChanged(nameof(CanDownload));
if (!value)
{
CanManagePermissions = false;
if (!EnableViewOnly)
{
CanView = false;
}
if (!EnableNotifyOnUpload)
{
NotifyOnUpload = false;
}
}
else
{
CanView = true;
}
HasChanged = true;
RaisePropertyChanged(nameof(EnableNotifyOnUpload));
RaisePropertyChanged(nameof(PermissionSummary));
}
}
}
public bool CanDelete
{
get
{
return AccessControl.CanDelete.GetValueOrDefault();
}
set
{
if (AccessControl.CanDelete != value)
{
AccessControl.CanDelete = value;
RaisePropertyChanged(nameof(CanDelete));
if (!value)
{
CanManagePermissions = false;
}
else
{
CanDownload = true;
CanUpload = true;
}
HasChanged = true;
RaisePropertyChanged(nameof(PermissionSummary));
}
}
}
public bool EnableViewOnly => Preferences.EnableViewOnly;
public bool CanView
{
get
{
return AccessControl.CanView.GetValueOrDefault();
}
set
{
if (AccessControl.CanView != value)
{
AccessControl.CanView = value;
if (!value)
{
CanDownload = false;
CanUpload = true;
}
if (!EnableNotifyOnUpload)
{
NotifyOnUpload = false;
}
HasChanged = true;
RaisePropertyChanged(nameof(CanView));
RaisePropertyChanged(nameof(EnableNotifyOnUpload));
RaisePropertyChanged(nameof(PermissionSummary));
}
}
}
public bool CanManagePermissions
{
get
{
return AccessControl.CanManagePermissions.GetValueOrDefault();
}
set
{
if (AccessControl.CanManagePermissions != value)
{
AccessControl.CanManagePermissions = value;
RaisePropertyChanged(nameof(CanManagePermissions));
if (value)
{
CanDelete = true;
CanUpload = true;
CanDownload = true;
}
else if (!EnableNotifyOnDownload)
{
NotifyOnDownload = false;
}
HasChanged = true;
RaisePropertyChanged(nameof(EnableNotifyOnDownload));
RaisePropertyChanged(nameof(PermissionSummary));
}
}
}
public bool EnableNotifyOnUpload => CanDownload || (CanView && !ShowDownloadLinkInUploadNotification);
public bool NotifyOnUpload
{
get
{
return AccessControl.NotifyOnUpload.GetValueOrDefault();
}
set
{
if (NotifyOnUpload != value && CanDownload)
{
AccessControl.NotifyOnUpload = value;
HasChanged = true;
}
else
{
AccessControl.NotifyOnUpload = false;
}
RaisePropertyChanged(nameof(NotifyOnUpload));
}
}
public bool EnableNotifyOnDownload => CanManagePermissions || AllowDownloadNotificationsWithoutAdmin;
public bool NotifyOnDownload
{
get
{
return AccessControl.NotifyOnDownload.GetValueOrDefault();
}
set
{
if (NotifyOnDownload != value)
{
AccessControl.NotifyOnDownload = value;
if (value && !AllowDownloadNotificationsWithoutAdmin)
{
CanManagePermissions = true;
}
HasChanged = true;
RaisePropertyChanged(nameof(NotifyOnDownload));
}
}
}
public string PermissionSummary
{
get
{
//...Returns a string based on the above properties...
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}