8

I've created the following attribute:

[Serializable]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class OperationPermissionAttribute : CodeAccessSecurityAttribute
{
    private static PrincipalPermission _revoke = new PrincipalPermission(PermissionState.None);
    private static PrincipalPermission _allow = new PrincipalPermission(PermissionState.Unrestricted);
    private string _role;
    private string _task;
    private string _operation;

    public OperationPermissionAttribute(SecurityAction action, string role, string task, string operation) : base(action)
    {
        _role = role;
        _task = task;
        _operation = operation;
    }

    public OperationPermissionAttribute(string role, string task, string operation)
        : base(SecurityAction.Demand)
    {
        _role = role;
        _task = task;
        _operation = operation;
    }

    public override System.Security.IPermission CreatePermission()
    {
        var principal = System.Threading.Thread.CurrentPrincipal as AzManPrincipal;
        if (principal == null)
            return _revoke;

        bool result = principal.IsOperationAllowed(_role, _task, _operation);
        return result ? _allow : _revoke;
    }
}

which I use like this:

    [OperationPermission(SecurityAction.Demand, Roles.Administrator, "UserService", "Remove")]
    public void Add(User user)
    {
        user.ValidateOrThrow();
        _repository.Add(user);
    }

Running the code gives me the following error:

Missing a required constructor. (Exception from HRESULT: 0x8013143B), its a COMException.

why on earth do I get it and what does it really mean?

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • I don't recognize 'Roles.Administrator'. Are you trying to run this in .NET 4.0? CAS is deprecated. – Hans Passant Aug 27 '10 at 14:29
  • Its a static class with our own roles. – jgauffin Aug 27 '10 at 16:56
  • What should I use instead of CAS? – jgauffin Aug 27 '10 at 17:00
  • 3
    @Hans: There are a couple of problems with your statement. First, CAS is not really deprecated in .NET 4.0 even if the "naked" CLR host no longer enforces CAS policy. Second, principal permissions are not true CAS permissions, and their evaluation has not been affected by the changes to CAS policy enforcement in .NET 4.0. – Nicole Calinoiu Aug 30 '10 at 12:54

2 Answers2

8

The problem lies in your constructor definitions. You need to replace your two existing constructors by a single constructor that takes only a SecurityAction argument. (See the "Notes to Inheritors" section at http://msdn.microsoft.com/en-us/library/system.security.permissions.codeaccesssecurityattribute.aspx.) The reason for this lies in the deserialization mechanism used for permission attributes.

Nicole Calinoiu
  • 20,843
  • 2
  • 44
  • 49
0

I would either change the constructor parameter type for role from String to Roles (in which case you would need to change a few other things as well)

public OperationPermissionAttribute(SecurityAction action, Roles role, ...

or do ToString() on the constructor call:

[OperationPermission(SecurityAction.Demand, Roles.Administrator.ToString(), "UserService", "Remove")]

I'd personally prefer the first option.

SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
  • We are using our own custom roles, hence the usage of strings. But that's not the cause of my error? – jgauffin Aug 27 '10 at 16:58