New Posts New Posts RSS Feed: Setting properties to the "current user" on Create and Modify
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Setting properties to the "current user" on Create and Modify

 Post Reply Post Reply
Author
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Topic: Setting properties to the "current user" on Create and Modify
    Posted: 08-Aug-2008 at 1:00pm
Hi,

I am working on a Cabana-style app (used the wizards, etc) and know there is some basic authentication stuff available via the LoginManager.

All of my BOs have the following table-based properties:

.DateAdded
.AddedBy
.DateLastModified
.ModifiedBy

What I would like to do is the following:

1. When a new object is created, set the .DateAdded to DateTime.Now and set the .AddedBy to the current logged in user.

2. When an object is modified and saved back to the data store, set the .DateLastModified to DateTime.Now and set the .ModifiedBy to the current logged in user.

So, right now all my BOs are inheriting from "BaseEntity" and each has its own .Create() method.

My questions:

A) Where should I put the code to set the Added information? In the Base Entity? In each BO's Create Method? Somewhere else?

B) Where should I put the code to set the Modified information? In the Base Entity? In each BO? Somewhere else?

C) How do I access the current application user? The Persistence Manager has an 'IsLoggedIn' property, but nothing about WHO is logged in, as far as I can tell...

Thanks!

Heather




Edited by HFloyd - 08-Aug-2008 at 1:01pm
Back to Top
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Posted: 15-Aug-2008 at 2:57pm
Okay, so I tried to figure this out myself.

ISSUE #1: WHERE DO I PUT THE CODE?
First of all, since I don't know a better way to do this, I added all my Added/Modifed code to the BaseEntity in a new method:

 /// <summary>
    /// Sets the Create and Update information
    /// </summary>
    protected void SetCreateUpdateInfo()
    {
        //Get current logged in user //["UserId"]
        IPrincipal ipCurrent = Thread.CurrentPrincipal;
        long lngUserId = (long)AppIdentity.GetUserIdFromPrincipal(ipCurrent);

        //Check if this is a new record
        if (this["AddedBy"] == null || (long)this["AddedBy"] == 0)
        {
            this["AddedBy"] = lngUserId;
            this["DateAdded"] = DateTime.UtcNow;
        }
        else
        {
            this["ModifiedBy"] = lngUserId;
            this["DateLastModified"] = DateTime.UtcNow;
        }
               
    }


Then I just add a call to this in my various Create routines:

...
        aNewObject.SetCreateUpdateInfo();
        aNewObject.AddToManager();
...


Perhaps someone has a better idea, but this seems to be functioning according to my requirements for now.

Though this does create a question - where should I put the same call for "Update"?

ISSUE #2: HOW DO I GET THE CURRENTLY LOGGED IN USER?
My bigger issue is that I am having a hard time using IPrincipal to get my UserId for the method.  This is what I am using in the method above:

...
        //Get current logged in user //["UserId"]
        IPrincipal ipCurrent = Thread.CurrentPrincipal;
        long lngUserId = (long)AppIdentity.GetUserIdFromPrincipal(ipCurrent);
...


Now, I did update the login manager to attach the logged in user to the Thread:

    public IPrincipal Login(ILoginCredential pCredential, PersistenceManager pManager) {

      EnterLogin();

      AppIdentity identity = GetAppIdentity(pCredential, pManager);
      String[] roles = GetUserRoles(pManager, identity);
      IPrincipal principal = new GenericPrincipal(identity, roles);

      //Added by HLF
      // bind the generic principal to the thread
      Thread.CurrentPrincipal = principal;

      ExitingSuccessfully();

      return principal;
    }


And if I put a breakpoint in 'SetCreateUpdateInfo()' and check the data, ipCurrent seems to be holding my expected data, but "AppIdentity.GetUserIdFromPrincipal(ipCurrent);" always returns zero. I noticed that the AppIdentity code is buried in "Foundation" and wasn't sure if I was supposed to change something here, or if it should work as expected. I have a class called "User" which has a field called "Id" (linked to the User table in my database also), but I'm not sure how GetUserIdFromPrincipal looks up the corresponding User.Id and returns it. I am not very familair with how Interfaces work, so please excuse any obvious ignorance.

If anyone has an idea of how I can get this to function as expected, I'd appreciate it.

Thanks,

Heather
Back to Top
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Posted: 15-Aug-2008 at 9:06pm
I noticed that the Login Manager was calling DummyUser, so I make a copy of that and called it CurrentUser and had it look to see if there was a matching User Entity (based on login/password), to set the ID, etc of CurrentUser, and that seems to work, though I'm not sure if it is considered "Best Practice"

/// <summary>
    /// Authenticate a user by username/password credentials
    /// </summary>
    /// <param name="pm"></param>
    /// <param name="credential"></param>
    /// <returns>
    /// An IUser implementation if the user is authenticated
    /// Null if not
    /// </returns>
    public static IUser GetUserByCredential(PersistenceManager pm, ILoginCredential credential) {
        CurrentUser user = new CurrentUser();

        //added by HLF
        //lookup the user in the Users table
        for (int i = 0; i < pm.GetEntities<User>().Count; i++)
        {
            User oTest = pm.GetEntities<User>();

            if (oTest.UserLogin == credential.UserName & oTest.UserPassword == credential.Password)
            {
                user.mId = oTest.Id;
                user.mUserName = oTest.FullName;

                return user;
            }

        }
        //if we got here, no valid user was found
        //TODO: should probably raise some sort of exception...
        return null;
    }



Back to Top
HFloyd View Drop Down
Groupie
Groupie


Joined: 27-Jul-2007
Location: United States
Posts: 44
Post Options Post Options   Quote HFloyd Quote  Post ReplyReply Direct Link To This Post Posted: 27-Aug-2008 at 9:40am
Hmm.. I'm still not quite sure where I should put the call for "SetCreateUpdateInfo()" for record modification... Is there some obvious spot? Or do I need to call it in a loop before pm.SaveChanges?
Any ideas appreciated...
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down