Similar questions have been asked before but not quite the same (unless I missed it)
I want to pass IUserInfo class instance through my Service, Domain , Domain Events, Domain Event Handlers...
Whats is the best way to do it.
Should I
Inject it using IoC by registering it
against instance of Httpcontext.Current.session["CurrentUser"];
Add the data to Current Thread.
Any other way
I am stuck at Domain Event Handlers where I want to use the data for auditing as well as sending emails.
I want to be able to use the CurrentUser information from almost anywhere in my application.
With threading as threads are pooled I am skeptical if the reuse of threads will reset the data. If not please shopw me how to use threading to pass IUser instance.
Regards,
Mar
My approach might not be ideal, but I find it working quite well. Thing what I did - I decided not to use dependency injection pass current user everywhere directly because that was getting too cumbersome and switched to static context. Problem with contexts - they are a bit difficult to manage.
This one is defined in my domain:
public static class UserContext{
private static Func<User> _getCurrentUser;
private static bool _initialized;
public static User Current{
get{
if(!_initialized)
throw new Exception("Can i haz getCurrentUser delegate?");
var user=_getCurrentUser();
return user??User.Anonymous;
}
}
public static void Initialize(Func<User> getCurrentUser){
_getCurrentUser=getCurrentUser;
_initialized=true;
}
}
Note that delegate is static - for whole app only one at a time. And I'm not 100% sure about it's life cycle, possible memory leaks or whatnot.
Client application is responsible to initialize context. My web application does that on every request:
public class UserContextTask:BootstrapperTask{
private readonly IUserSession _userSession;
public UserContextTask(IUserSession userSession){
Guard.AgainstNull(userSession);
_userSession=userSession;
}
public override TaskContinuation Execute(){
UserContext.Initialize(()=>_userSession.GetCurrentUser());
return TaskContinuation.Continue;
}
}
Using mvcextensions library to stream-line bootstrapping tasks. You can just subscribe for according events in global.asax for that.
In client side (web app), I implement application service named IUserSession:
public User GetCurrentUser(){
if(HttpContext.Current.User==null) return null;
var identity=HttpContext.Current.User.Identity;
if(!identity.IsAuthenticated) return null;
var user=_repository.ByUserName(identity.Name);
if(user==null) throw new Exception("User not found. It should be. Looks bad.");
return user;
}
There is some more lame code necessary in order to use forms auth with roles w/o membership provider and role provider. But that's not the point of this question.
At domain level - I'm explicitly describing permissions that users might have like this one:
public class AcceptApplications:IUserRights{
public bool IsSatisfiedBy(User u){
return u.IsInAnyRole(Role.JTS,Role.Secretary);
}
public void CheckRightsFor(User u){
if(!IsSatisfiedBy(u)) throw new ApplicationException
("User is not authorized to accept applications.");
}
}
Cool thing is - those permissions can be made more sophisticated. E.g.:
public class FillQualityAssessment:IUserRights{
private readonly Application _application;
public FillQualityAssessment(Application application){
Guard.AgainstNull(application,
"User rights check failed. Application not specified.");
_application=application;
}
public bool IsSatisfiedBy(User u){
return u.IsInRole(Role.Assessor)&&_application.Assessors.Contains(u);
}
public void CheckRightsFor(User u){
if(!IsSatisfiedBy(u))
throw new ApplicationException
("User is not authorized to fill quality assessment.");
}
}
Permissions can be checked vica versa too - User has these fellas:
public virtual bool HasRightsTo<T>(T authorizationSpec) where T:IUserRights{
return authorizationSpec.IsSatisfiedBy(this);
}
public virtual void CheckRightsFor<T>(T authorizationSpec) where T:IUserRights{
authorizationSpec.CheckRightsFor(this);
}
Here's my aggregate root base class:
public class Root:Entity,IRoot{
public virtual void Authorize(IUserRights rights){
UserContext.Current.CheckRightsFor(rights);
}
}
And here's how I check permissions:
public class Application{
public virtual void Accept(){
Authorize(new AcceptApplications());
OpeningStatus=OpeningStatus.Accepted;
}
}
I hope that helps...
I've done this kind of thing before using IoC. The benefit of this is that it's very testable -- you can stub out your user info for testing -- and reasonably readable and easy to follow.
Related
I have a simple service interface I am using to synchronize data with a server via HTTP. The service interface has a method to start and stop the synchronization process. The idea is to start the synchronization process after the user signs in, and stop the synchronization at the end of the application before the user signs out. The synchronization service will check for new messages every few minutes, and then notify the ViewModel(s) of new/changed data using the MvxMessenger plugin.
What is the recommended way to ensure the synchronization service lives for the duration of the app? I am currently using a custom IMvxAppStart which registers the service interface as a singleton, and then holds a static reference to the service interface. Is that enough to keep the service alive for the lifetime of the app, or is there a better way?
public class App : MvxApplication
{
public override void Initialize()
{
...
RegisterAppStart(new CustomAppStart());
}
}
public class CustomAppStart : MvxNavigatingObject, IMvxAppStart
{
public static ISyncClient SynchronizationClient { get; set; }
public void Start(object hint = null)
{
SynchronizationClient = Mvx.Resolve<ISyncClient>();
ShowViewModel<SignInViewModel>();
}
}
public interface ISyncClient
{
void StartSync();
void StopSync();
bool IsSyncActive { get; }
}
You don't need a static property for this. When you register the Interface as a singleton, the IoC do the work for you. Example: In one of our apps wee need a state-property with important data for the whole lifetime of the app.
The models who need this state, just uses following code snippet:
protected IApplicationState AppState
{
get { return _appstate ?? (_appstate = Mvx.GetSingleton<IApplicationState>()); }
}
private IApplicationState _appstate;
But: You can do it also with a static property. But in this case you don't need a singleton-value in the IoC.
My current implementation of passing UserID in my application is through the constructor.
i.e. SomeObject s = new SomeObject(userID)
Where in there is a code behind that does things based on the userID. The userID is further keep tracked by adding another property named "CurrentUser", however this seems to be a dirty solution as I have to implement it to all ViewModels and it seems to violate the "DRY" concept.
The second approach I have in mind is creating a public static variable on my MainWindowViewModel where all my other models can refer to it as MainWindowViewModel.CurrentUser.
Is one of the two approach the correct way to do this or is there a better approach that i don't know about?
You need to carefully analyze up front what you want to achieve with your application. Are you happy with there only ever being one selected client? Or will you need to have multiple clients being viewed or edited at a time (i.e. you have an MDI style app)?
Going with the single client approach is easy, you can implement the global property bag as already mentioned in other answers. But I will advise caution: if you build your app on the assumption there will only ever be one selected client it becomes a real PITA to try to refactor to make it multi-client capable. Using a centralized property bag or "session service" like this is indeed decoupling state from the VM, but the centralized service can still turn into a monstrosity over time and you build up too much dependence on it.
If you do want to go the multi-client route, then you are on the right track - but instead of passing a client identifier in on the constructor, pass (inject) the entire client data object. The chances are that you already have most of the client details available from the piece of UI that invokes the client oriented VM, so pass it in and save having to make another trip to your database to get the details.
Don't tie a current user to a ViewModel. I typically opt for a SessionService of some kind. If you're using Dependency Injection (DI), register a singleton of an ISessionService and concrete implementation. If your not using DI, then just have your app start create a singleton, like a SessionService.Current. Then you can put any items you need in here. Then each ViewModel can ask for the SessionService.Current.User and they have it. Your ViewModels shouldn't know about each other, but they can know about services. This keeps it DRY and loosely coupled, especially if you only access these session variables using the interface of an ISessionService and not the concrete implementation. This allows you to mock one up very easily without changing any ViewModel code.
What you have here is the problem of Communication between ViewModels. There are a number of solutions but my fave is the Mediator Pattern:
using System;
namespace UnitTestProject2
{
public class GetDataViewModel
{
IMediator mediator;
public GetDataViewModel(IMediator mediator)
{
this.mediator = mediator;
this.mediator.ListenFor("LoggedIn", LoggedIn);
}
protected string UserId;
protected void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
IMediator mediator;
public LoginViewModel(IMediator mediator)
{
this.mediator = mediator;
}
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
this.mediator.RaiseEvent("LoggedIn", this.UserId);
}
}
public interface IMediator
{
public void ListenFor(string eventName, EventHandler action );
public void RaiseEvent(string eventName, object data);
}
}
I Haven't implemented the Mediator here, because it can get quite involved and there are a number of packages available. but you can see the idea from my simple interface. Essentially the Mediator provides a Global list of EventHandlers which any Viewmodel can call or add to. You still have the problem of where to store the event names. Its nice to have these in enums, but that gives you a coupling problem. (a problem I usually ignore)
Alternatively you can have a Controller or (MasterViewModel if you love MVVM)
using System;
namespace UnitTestProject3
{
public class GetDataViewModel
{
protected string UserId;
public void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
public EventHandler OnLogin;
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
if (this.OnLogin != null)
{
this.OnLogin(this.UserId, null);
}
}
}
public class Controller // or MasterViewModel
{
public void SetUp()
{
GetDataViewModel vm1 = new GetDataViewModel();
LoginViewModel vm2 = new LoginViewModel();
vm2.OnLogin += vm1.LoggedIn;
//wire up to views and display
}
}
}
Throughout my ASP.net site i need to check if the logged in users belongs to a role or has a field in my "UserInstance" table in my database set to true. To do this i can do the following.
if(Roles.IsUserInRole("Global Admin")
|| uow.UserInstanceService.GetUserInstance(userId,InstanceId).Admin)
{
//Do something
}
However as i am going to be using this code a lot as much of the permissions depend on the logged in user either being a "Global Admin" or a field of my table being true I don't want to write this out constantly.
One solution i have found is to create a method in the "UserInstance" Service which checks for both as seen in the "IsUserAdminOrGlobalAdmin" method.
public class UserInstanceService
{
IRepository<UserInstance> userInstanceRepository;
public UserInstanceService(IRepository<UserInstance> userInstanceRepository)
{
this.userInstanceRepository = userInstanceRepository;
}
public UserInstance GetByUserIdAndInstanceId(Guid userId, int instanceId)
{
return userInstanceRepository.GetSingle(u => u.UserId == userId && u.InstanceId == instanceId);
}
public bool IsUserAdminOrGlobalAdmin(Guid userId,int instanceId)
{
bool valid = false;
if (System.Web.Security.Roles.IsUserInRole("Global Admin"))
valid = true;
if (GetByUserIdAndInstanceId(userId, instanceId).Admin)
valid = true;
return valid;
}
//Removed rest of methods for readability
}
As this is buisness logic I put this method is in my "UserInstanceService" class which interacts with the repository class which contains the entity context. This service class resides in a seperate Model project so i had to add a reference to System.Web.Security and i am not sure if doing this is good practice. One thing i have noticed is that i can not write unit tests for this method as it relies on a user being logged in.
So my question is, is it acceptable to combine HttpContext specific functionality like the Logged in users roles, in a service?
Edit - After reading the answers I have changed my code so a Auth service (in the Web app project) is called which in turn calls the UserInstanceService to something like this.
public class Auth: IAuthService {
public bool IsUserAdminOrGlobalAdmin(Guid userId,int instanceId) {
myEntities entityContext = new myEntities
//RepsitoryBase inherits my IRepository<TEntity> class
UserInstanceService uis = new UserInstanceService(new RepositoryBase<UserInstance>(entityContext));
bool valid = false
if(Roles.IsUserInRole("Global Admin"))
valid = true;
if(uis.GetByUserIdAndInstanceId(userId,instanceId).Admin)
valid = true;
return valid;
}
}
So i could call this in my pages like this
if(Auth.IsUserAdminOrGlobalAdmin(userId,InstanceId)
{
//Do stuff
}
The original answer was written assuming the UserAccess requires the Authentication, but it appears that the Authentication consumes the UserAccess; simply invert the dependencies, but everything else should be usable in about the same manner.
Original answer:
Pull the ASP.NET-specific code into it's own service separate from the repository. Then that service - say, the Auth Service - can be used by any component (such as the UserInstanceService) that needs access to centralized authentication/authorization logic.
Consume the Auth as a dependency per IoC principles, hopefully using some DI to make life easier.
If the Auth service is kept separate it can also be trivially mocked for testing, such as testing what happens when the use is authenticated or not, which entirely avoids the need to setup a full ASP.NET stack for the User service.
In addition, because services (interfaces) and components (classes) are separate, the actualy HTTP-utilizing component can live in a separate project from the service and wired in later - this will avoid pulling in Web dependencies to the Model project.
For example,
// This is the Service Contract and can live in the Model
public class IAuthService {
void AssertCurrentUserIsAdminOrGlobalAdmin();
void AssertIsUserAdminOrGlobalAdmin(Guid userId,int instanceId);
}
// This is the Component, which provides the Service, and is part
// of the Web/HTTP-specific project. It is wired up via IoC/DI from
// the large context of the application.
public class Auth: IAuthService {
public void AssertCurrentUserIsAdminOrGlobalAdmin() {
// This one already knows the applicable HTTP/User Context
}
public void AssertIsUserAdminOrGlobalAdmin(Guid userId,int instanceId) {
// Do whatever
}
}
// This Component is part of the Model
public class UserInstanceService
{
// IoC dependencies
IRepository<UserInstance> userInstanceRepository;
IAuthService authService;
}
You could set the current principal on the thread and use that instead. I think thats most of what ASP.Net does for you as well.
As a part of learning process, I am writing simple IM app, using Remoting in .NET. As of now it is simple console app and it works as i expect. Thinking about next features/functionalities, I've stuck in a situation represented by the code below:
public static class UserManager {
public static started { get; private set; }
private static List<User> users;
static UserManager() {
users = List<User>();
started = true;
}
public static addUser(int _userID) {}
public static activateUser(int _userID) {
foreach (User u in users) {
if (u.userID == _userID) {
u.setActive();
break;
}
}
}
}
class User {
public int userID { get; private set; }
public bool active { get; private set; }
public User(int _userID) {
userID = _userID;
}
public void setActive() {
// only UserManager should be allowed to modify user state
}
}
I want to make only UserManager static class be allowed to modify states of it's users list. I was thinking about "friend" clause but as I understand, there is no such construct in C#. Would it be enough just checking (inside User class methods), if calling "object" is of class UserManager?
I would appreciate any input/advice, including those saying "don't do that as You try to do, better make it using.."
PS. Didn't know which Title should i choose, feel free (more experienced programmers/so users) to change it if ther is more accurate.
You can put the UserManager and User classes in their own assembly and mark parts of the API as internal (which is the equivalent of VB's Friend). This enables you to restrict access from outside that assembly.
Another way to restrict access is by doing role based security. .NET has the PrincipalPermissionAttribute for this:
public static class UserManager
{
[PrincipalPermission(SecurityAction.Demand,
Role = "Administrators")]
public static void AddUser(int userId) { }
}
Note that this will only work when you know the role of the user, but it is especially useful in scenario's such as web sites (ASP.NET WebForms / MVC) and web services (WCF) were users normally log on.
The only options I can think of for really restricting access to the members of User to UserManager at compile time are:
Put the two of them in their own assembly, and make the members internal
Make UserManager a nested class within User and make the members private
If you just make the members internal, it will limit access to the assembly anyway - can you not make the assembly sufficiently small that you can trust code written within that assembly?
(Just as a friendly bit of advice, I suggest you look up the Microsoft .NET naming conventions - it'll make your code look much more like idiomatic C#.)
I am trying to avoid the conventional:
if(!user.HasPermission(Actions.UpdateRecord))
{
// code to update record
}
on a large number of permissions all over my application.
I am looking for a means of checking for permissions in an effective and (if possible) elegant manner.
In this case there are multiple actions within each permission.
How about putting a decorator on your dataaccess objects. The decorator pattern is very useful for doing things like handling permissions. Your dataAccess layer can do just data access and then your decorate those classes with something that handles permissions and permissions only.
It is very elegant...
http://en.wikipedia.org/wiki/Decorator_pattern
There are a lot of ways to do this. The important thing is that you want to encapsulate the concern of checking permissions. One way to do this is with a strategy pattern. Encapsulate the action in a class, and get the class via a factory method. The factory can do the security check, and return a different strategy for disallowed actions.
For example:
public abstract class SecureAction
{
public void PerformAction();
}
public class UpdateRecords : SecureAction
{
public void PerformAction()
{
//code to do the update
}
}
public class DoesNotHavePermissionAction : SecureAction
{
public void PerformAction()
{
//code to handle missing permissions
}
}
public class SecureActionFactory
{
public void GetUpdateRecordsAction(User user)
{
if(user.HasPermissions(Actions.UpdateRecord)) {return new UpdateRecordsAction();}
return new DoesNotHavePermissionAction();
}
}