2
\$\begingroup\$

Below comes a Value Object to represent UserId in ASP.NET application. It implements Value Identity, so equality is defined by matching of the state calculated at the moment of comparison. It depends on

public interface IAuthenticator
{
 int CurrentUserId { get; } // may be impersonated 
 int InteractiveUserId { get; } // "real" user, may impersonate
}

which extracts state from ClaimIdentity.

Here is a definition:

public struct UserId 
{
 public static IAuthenticator Authenticator { get; set; }
 public static readonly UserId Anonymous = 
 new UserId(() => 0);
 public static readonly UserId Current = 
 new UserId(() => Authenticator?.CurrentUserId ?? 0);
 public static readonly UserId Interactive = 
 new UserId(() => Authenticator?.InteractiveUserId ?? 0);
 public UserId(int value)
 : this(() => value)
 {
 }
 UserId(Func<int> getValue)
 : this()
 {
 GetValue = getValue;
 }
 public bool Authenticated => this == Current && this != Anonymous;
 public bool Impersonated => this == Current && Current != Interactive;
 public bool Impersonating => this == Interactive && Current != Interactive;
 Func<int> GetValue { get; }
 int Value => GetValue?.Invoke() ?? 0;
 public static implicit operator int(UserId id) => id.Value;
 public static bool operator ==(UserId left, UserId right) =>
 left.Value == right.Value;
 public static bool operator !=(UserId left, UserId right) =>
 left.Value != right.Value;
 // Equals, GetHashCode are omitted for brevity
}

We can do the following now:

 if(UserId.Current.Authenticated) ...
 if(UserId.Current.Impersonated) ...
 if(UserId.Interactive.Impersonating) ...

Also:

 var uid = new UserId(33);
 if(uid.Authenticated) ...
 if(uid.Impersonated) ...
 if(uid.Impersonating) ...

And provide overloads in extension methods:

 interface IAuthorizer
 {
 void Authorize<TResource, TAction>(int resourceId, UserId userId);
 } 
 static class AuthorizerExtensions
 {
 public static void Authorize<TResource, TAction>(
 this IAuthorizer authorizer, int resourceId) =>
 authorizer.Authorize<TResource, TAction>(resourceId, UserId.Current); 
 } 

It is intended to be used here. GitHub repository (just a sketch).

Do these terms (Anonymous, Current, Interactive, Authenticated, Impersonated, Impersonating) properly used here and look understandable? Do they have an expected behavior?

asked Apr 1, 2016 at 13:58
\$\endgroup\$
2

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.